ΠΡΡΠΎΡΠΈΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ
Changelog / DevLog
ΠΠΈΠΆΠ΅ β ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½ΡΠ½Π½ΡΠΉ ΠΆΡΡΠ½Π°Π» ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠΈ Π΄Π²ΠΈΠΆΠΊΠ° ΠΈ ΠΈΠ½ΡΡΠ°ΡΡΡΡΠΊΡΡΡΡ. ΠΠ°ΠΏΠΈΡΠΈ ΠΎΡΡΠΎΡΡΠΈΡΠΎΠ²Π°Π½Ρ ΠΏΠΎ Π΄Π°ΡΠ΅.
23.07.2025
Π― Π½Π°ΡΠ°Π» Π΄Π΅Π»Π°ΡΡ ΡΠ²ΠΎΠΉ Π΄Π²ΠΈΠΆΠΎΠΊ Π΄Π»Ρ MMORPG Π½Π° C++ Π½Π° ΠΏΠ°ΡΡΠ΅ΡΠ½Π΅ ECS.
04.08.2025
ΠΠ°ΠΏΠΈΡΠ°Π» Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊ. ΠΡΠΈΠΌΠ΅Π½ΡΡ ΡΡΡΠΎΠ³ΡΡ ΡΠΈΡΡΡΡ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ (Onion Architecture) Ρ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΠΎΠΉ ΠΊΠΎΠ³Π΅Π·ΠΈΠ΅ΠΉ.
ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ:
- CallStack β ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠ° ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ ΡΡΠ΅ΠΊΠ° Π²ΡΠ·ΠΎΠ²ΠΎΠ² Π² Π»ΠΎΠ³Π΅.
- Debug β Π΅Π΄ΠΈΠ½Π°Ρ ΡΠΈΡΡΠ΅ΠΌΠ° Π»ΠΎΠ³ΠΎΠ². ΠΠ»Ρ Godot ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΡΡ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄Ρ ΠΈ ΠΎΡΡΡΡΡΡΠ²ΡΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ, ΠΏΠΎΡΡΠΎΠΌΡ Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ Π΅ΡΡΡ Π²Π΅ΡΡΠΈΡ Π΄Π»Ρ Godot Ρ Π°Π΄Π°ΠΏΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠΌ Π²ΡΠ²ΠΎΠ΄ΠΎΠΌ.
- DI β ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅Ρ Π²Π½Π΅Π΄ΡΠ΅Π½ΠΈΡ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ Π΄Π»Ρ ECS-ΠΌΠΈΡΠ°.
- Core β Π±Π°Π·ΠΎΠ²ΡΠΉ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π» ECS: ΠΌΠΈΡΡ, ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ, ΡΡΡΠ½ΠΎΡΡΠΈ.
- JsonSerialization β ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ/Π΄Π΅ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ Π΄Π°Π½Π½ΡΡ ΠΌΠΈΡΠ° Π² JSON ΠΈ ΠΎΠ±ΡΠ°ΡΠ½ΠΎ.
- Network β ΠΊΠ»ΠΈΠ΅Π½ΡβΡΠ΅ΡΠ²Π΅ΡΠ½Π°Ρ Π»ΠΎΠ³ΠΈΠΊΠ° ΠΈ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ Π΄Π°Π½Π½ΡΡ ΡΡΡΠ½ΠΎΡΡΠ΅ΠΉ.
- Multiplayer β ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΊΠ»ΠΈΠ΅Π½ΡΠΎΠ², ΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π³Π΅ΡΠΎΡ ΠΏΠΎ Π΄Π°Π½Π½ΡΠΌ ΠΠ, Π²ΡΠ±ΠΎΡ ΠΌΠΈΡΠ°.
- Engine β ΡΠ΅ΡΠ΄ΡΠ΅Π²ΠΈΠ½Π° Π΄Π²ΠΈΠΆΠΊΠ°, Π±Π°Π·ΠΎΠ²Π°Ρ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ.
- Gameplay β ΠΈΠ³ΡΠΎΠ²Π°Ρ Π»ΠΎΠ³ΠΈΠΊΠ°.
Π‘Π΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ:
- Π Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ/Π΄Π΅ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΡΠΈΡΡΠ΅ΠΌ ΠΈ ΡΡΡΠ½ΠΎΡΡΠ΅ΠΉ ΠΌΠΈΡΠ°.
- ΠΠ· ΡΡΠ΅Π½Ρ Godot ΠΏΡΠΈ ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΠΈ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ Π³Π΅Π½Π΅ΡΠΈΡΡΠ΅ΡΡΡ Π²ΡΠΏΠΎΠΌΠΎΠ³Π°ΡΠ΅Π»ΡΠ½Π°Ρ ΡΡΠ΅Π½Π° Ρ Π΄Π°Π½Π½ΡΠΌΠΈ ECS, ΠΊΠΎΡΠΎΡΡΡ Π·Π°ΡΠ΅ΠΌ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π³ΡΡΠ·ΠΈΡΡ Π² ECS-ΠΌΠΈΡ. ΠΡΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΈ Π΄Π»Ρ ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΠΉ Π² ΠΎΠ΄ΠΈΠ½ΠΎΡΠ½ΠΎΠΉ ΠΈΠ³ΡΠ΅.
- Π Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Π΄Π»Ρ ΡΠ΅ΡΠ΅Π²ΠΎΠΉ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΠΈ.
ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Ρ Godot:
ΠΠΎΠ΄ ΠΊΠ°ΠΆΠ΄ΡΡ Π²Π½ΡΡΡΠ΅Π½Π½ΡΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΡ Π΄Π²ΠΈΠΆΠΊΠ° ΠΏΡΠΈ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΠΈ ΡΡΡΠ΅ΡΡΠ²ΡΠ΅Ρ ΡΠ²ΡΠ·ΡΡΡΠ°Ρ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π΄Π»Ρ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ Ρ Godot.
CoreGodotEditor
β ΡΠ²ΡΠ·ΡΠ²Π°Π΅Ρ ΡΠ΅Π΄Π°ΠΊΡΠΎΡ Godot ΡCore
Π΄Π»Ρ ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ Π΄Π°Π½Π½ΡΡ ΡΡΡΠ½ΠΎΡΡΠΈ Π² ΠΈΠ½ΡΠΏΠ΅ΠΊΡΠΎΡΠ΅ Ρ Π²ΡΠ±ΡΠ°Π½Π½ΠΎΠ³ΠΎNode
.CoreGodotRuntime
β ΡΠ²ΡΠ·ΡΠ²Π°Π΅Ρ ΡΠ°Π½ΡΠ°ΠΉΠΌ Godot ΡCore
: Π΄Π°Π½Π½ΡΠ΅ ΡΡΡΠ½ΠΎΡΡΠ΅ΠΉ ΠΌΠ°ΠΏΠΏΡΡΡΡ Π½Π° ΡΠ²ΠΎΠΉΡΡΠ²Π°Node
(ΠΏΠΎΠ·ΠΈΡΠΈΡ, Π°Π½ΠΈΠΌΠ°ΡΠΈΡ ΠΈ Ρ. ΠΏ.), ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π½Π°ΡΡΡΠ°ΠΈΠ²Π°Π΅ΠΌΠΎ.
Π‘Π΅ΡΠ²Π΅Ρ ΠΈ Π½Π°Π³ΡΡΠ·ΠΎΡΠ½ΠΎΠ΅ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅:
Π Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Ρ Π±Π΅Π·Π³ΠΎΠ»ΠΎΠ²ΡΠΉ ΡΠ΅ΡΠ²Π΅Ρ ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ Π΄Π»Ρ Π½Π°Π³ΡΡΠ·ΠΎΡΠ½ΡΡ ΡΠ΅ΡΡΠΎΠ². Π‘Π΅ΡΠ²Π΅Ρ Ρ Π½ΡΠΆΠ½ΡΠΌΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ°ΠΌΠΈ Π²Π΅ΡΠΈΡ ~700 ΠΠ ΠΈ ΠΏΠΎΡΡΠ΅Π±Π»ΡΠ΅Ρ ~1.4 ΠΠ ΠΠΠ£.
Π‘ΡΠ°ΡΡΡ:
ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Π΄Π²ΠΈΠΆΠΊΠ° Π² Godot Π·Π°ΠΊΠΎΠ½ΡΠ΅Π½Π°. ΠΠ°Π»Π΅Π΅ β ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ Π΄Π°Π½Π½ΡΡ ΡΡΡΠ½ΠΎΡΡΠ΅ΠΉ ΠΌΠ΅ΠΆΠ΄Ρ Π΄Π²ΠΈΠΆΠΊΠ°ΠΌΠΈ.
21.08.2025 β Debug: v1.0.0
π ΠΠΎΡΠΎΠ²Π° ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½Π°Ρ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° ΠΎΡΠ»Π°Π΄ΠΊΠΈ Ρ Π»ΠΎΠ³Π³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΈ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΌ ΡΡΠ΅ΠΊΠΈΠ½Π³ΠΎΠΌ ΡΡΠ΅ΠΊΠ° Π²ΡΠ·ΠΎΠ²ΠΎΠ².
ΠΠ»ΡΡΠ΅Π²ΡΠ΅ ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡΠΈ:
- ΠΡΠ»ΡΡΠΈΠΏΠ»Π°ΡΡΠΎΡΠΌΠ΅Π½Π½ΠΎΡΡΡ: Π²Π΅ΡΡΠΈΡ Π΄Π»Ρ Godot (
UtilityFunctions::print
) ΠΈ standalone (stdout). - ΠΡΠ»Π΅Π²ΡΠ΅ Π½Π°ΠΊΠ»Π°Π΄Π½ΡΠ΅ ΡΠ°ΡΡ ΠΎΠ΄Ρ Π² ΡΠ΅Π»ΠΈΠ·Π΅: ΠΎΡΠ»Π°Π΄ΠΎΡΠ½ΡΠ΅ ΠΌΠ°ΠΊΡΠΎΡΡ Π²ΡΡΠ΅Π·Π°ΡΡΡΡ ΠΈΠ· Π±ΠΈΠ»Π΄Π°.
- Π’ΠΈΠΏΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ: Log, Warning, Error; Π½Π°ΡΡΡΠ°ΠΈΠ²Π°Π΅ΠΌΡΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΈ ΠΈ ΡΠ²Π΅ΡΠ°.
- ΠΠΈΠ±ΠΊΠΎΠ΅ ΡΠΎΡΠΌΠ°ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅: Π°ΡΠ³ΡΠΌΠ΅Π½ΡΡ (printf-ΡΡΠΈΠ»Ρ), ΠΏΠΎΡΠΎΠΊΠΎΠ²ΡΠΉ Π²ΡΠ²ΠΎΠ΄ (std::cout) ΠΈΠ»ΠΈ ΠΈΡ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°ΡΠΈΡ.
- ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΠ·Π°ΡΠΈΡ: ΠΌΠ°ΠΊΡΠΎΡΡ ΡΠΊΠ°Π·ΡΠ²Π°ΡΡ ΡΠ°ΠΉΠ» ΠΈ ΡΡΡΠΎΠΊΡ, Π²ΡΡΠ°Π²Π½ΠΈΠ²Π°Π½ΠΈΠ΅ ΡΡΠ΅ΠΊΠ° ΠΏΠΎ ΡΡΡΠΎΠΊΠ°ΠΌ, Π²ΠΈΠ·ΡΠ°Π»ΡΠ½ΡΠΉ Β«Π³ΡΠ°Π΄ΠΈΠ΅Π½ΡΒ» ΠΈ ΠΎΡΡΡΡΠΏΡ Π΄Π»Ρ ΡΠΈΡΠ°Π΅ΠΌΠΎΡΡΠΈ.
ΠΠ°ΠΊΡΠΎΡ _w()
ΠΈ ΠΏΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:
#include "Debug/Debug.hpp"
using namespace Debug;
namespace Debug_Tests {
class DebuggingTest {
public:
void runAllTests() {
_w();
_w(_testBasicLogging());
_w(_testMessageCustomization());
_w(_testAssertAndThrow());
_w(_testCallStackTracing());
_w(_testCombinedFormatting());
std::cout << "All tests completed successfully." << std::endl;
}
private:
void _testBasicLogging() {
_w();
DEBUG::Log("This is a standard log message.") << "qwe";
DEBUG::Warning("This is a warning message.") << "";
DEBUG::Error("This is an error message.");
}
void _testMessageCustomization() {
_w();
DEBUG::Message(
LogStream::Message("Custom message with sub title and other color.")
.SetTitle("[SUB_TITLE]")
.SetColor(Colors::TEXT_COLOR_CYAN_SOFT)
.ToString()
);
DEBUG::Message(
LogStream::Message("Message without a title.")
.NoTitle()
.ToString()
).NoTitle();
}
void _testAssertAndThrow() {
_w();
DEBUG::Assert(true, "This assert should pass.");
}
void _testCallStackTracing() { _w(); _innerFunction(); }
void _innerFunction() {
_w();
DEBUG::Log("Call stack tracing test: inside inner function.");
}
void _testCombinedFormatting() {
_w();
int p_score = 100; std::string p_player = "Player_One"; float p_speed = 15.5f;
DEBUG::Log("Player: ", p_player, ", Score: ", p_score, ", Speed: ", p_speed);
DEBUG::Log("Game_State: ") << "Running" << ", Level: " << 5 << ", Time: " << 120.5f;
DEBUG::Log("Combined Log. Level: ", 5) << " and " << "Score: " << 200;
}
};
}
26.08.2025 β DI: v1.0.0
π ΠΠ½Π΅Π΄ΡΠ΅Π½ΠΈΠ΅ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ (Dependency Injection) Π΄Π»Ρ ΡΠΈΡΡΠΎΠ³ΠΎ ΠΈ Π³ΠΈΠ±ΠΊΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°.
ΠΠ°ΠΊ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅Ρ:
- Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ (
registerSingleton
) β Ρ ΡΠ°Π½ΠΈΡ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΡ ΠΊΠ°ΠΊ ΡΠΈΠ½Π³Π»ΡΠΎΠ½Ρ (ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρshared_ptr
ΠΈΠ»ΠΈ ΡΡΡΠ»ΠΊΡ Π½Π° Π²Π½Π΅ΡΠ½ΠΈΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρstd::stringstream
). - ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ (
get
/getRaw
) β Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρshared_ptr
ΠΈΠ»ΠΈ ΡΡΡΠ»ΠΊΡ/ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ Π½Π° Π·Π°ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ. - Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Ρ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ΠΌ (
ResolveAndConstruct
) β Π°Π½Π°Π»ΠΈΠ·ΠΈΡΡΠ΅Ρ ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡ ΠΈ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΏΠΎΠ΄ΡΡΠ°Π²Π»ΡΠ΅Ρ Π·Π°ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ, ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΡ.
ΠΠΎΠ½ΡΠ΅ΠΉΠ½Π΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ DEBUG::Throw
Π΄Π»Ρ Π΄Π΅ΡΠ°Π»ΡΠ½ΡΡ
ΠΎΡΠΈΠ±ΠΎΠΊ ΠΏΡΠΈ ΠΎΡΡΡΡΡΡΠ²ΠΈΠΈ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ.
ΠΠ»ΡΡΡ: ΠΌΠΎΠ΄ΡΠ»ΡΠ½ΠΎΡΡΡ, ΡΠ΄ΠΎΠ±Π½ΠΎΠ΅ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ (mock-ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ), Π³ΠΈΠ±ΠΊΠΎΡΡΡ ΠΏΠΎΠ΄ΠΌΠ΅Π½Ρ, ΡΠΈΡΡΠ°Ρ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ.
Π‘ΠΈΡΡΠ΅ΠΌΠ° ΡΠ±ΠΎΡΠΊΠΈ (Builder): v1.0.0
Π‘ΠΎΠ·Π΄Π°Π½Π° ΠΊΡΠΎΡΡΠΏΠ»Π°ΡΡΠΎΡΠΌΠ΅Π½Π½Π°Ρ ΡΠΈΡΡΠ΅ΠΌΠ° ΡΠ±ΠΎΡΠΊΠΈ (C++/Python/CMake/Shell), ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΠΎΠ²Π°Π½Π½Π°Ρ Ρ Godot.
ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ°:
- ΠΠ±ΡΡΠ²Π»Π΅Π½ΠΈΠ΅ ΡΠ΅Π»Π΅ΠΉ ΡΠ½Π°ΡΠ°Π»Π° Π²ΠΎ Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΡ ΡΡΡΡΠΊΡΡΡΠ°Ρ , Π·Π°ΡΠ΅ΠΌ β Π·Π°Π³ΡΡΠ·ΠΊΠ° Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ ΠΈ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΡ ΡΠ΅Π»Π΅ΠΉ CMake.
- ΠΡΠ±ΠΎΡΠΎΡΠ½Π°Ρ ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΡ: Π²ΠΊΠ»ΡΡΠ°ΡΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π½ΡΠΆΠ½ΡΠ΅ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΌ ΠΏΠΎΠ΄ΡΡΠ³ΠΈΠ²Π°Π½ΠΈΠ΅ΠΌ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ.
ΠΠ΅ΠΊΠ»Π°ΡΠ°ΡΠΈΠ²Π½ΡΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ CMake:
Library(ECS default
SOURCES src/**/*.cpp
PUBLIC_DIRS ./include
PUBLIC_LIBS tp::entt
DI:SHARED Debug:SHARED Utils:SHARED)
Library(ECS Godot
SOURCES src/**/*.cpp
PUBLIC_DIRS ./include
PUBLIC_LIBS tp::entt
DI:STATIC Debug:STATIC Utils:STATIC)
Executable(ECS_Tests default
SOURCES tests/Tests.cpp
PUBLIC_DIRS
PRIVATE_LIBS ECS:SHARED)
CLI ΠΈ IDE:
- ΠΡΠ³ΡΠΌΠ΅Π½ΡΡ:
--rebuild
,--rebuild_dependencies
,--release
,--ninja
. - ΠΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΡΠΎΠ±ΠΈΡΠ°ΡΡ Π²ΡΠ±ΠΎΡΠΎΡΠ½ΠΎ:
WudgineBuilder ECS DI DEBUG
. - ΠΠ΅ΡΡΠΎΠ²Π½Π°Ρ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Ρ Godot:
Cmd+R
Π² ΡΠ΅Π΄Π°ΠΊΡΠΎΡΠ΅ Π·Π°ΠΏΡΡΠΊΠ°Π΅Ρ ΠΏΠΎΠ»Π½ΡΡ ΡΠ±ΠΎΡΠΊΡ, Π»ΠΎΠ³ΠΈ Π²ΡΠ²ΠΎΠ΄ΡΡΡΡ Π² Output, GDExtension Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ Π²addons
.
27.08.2025 β Jobs: v1.0.0
π ΠΠΎΠ»Π½Π°Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ API Unity Jobs Π½Π° C++.
ΠΡΠ½ΠΎΠ²Ρ: iJob
, iJobParallelFor
.
Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅: JobHandle
(Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ, ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅, ΡΡΠ°ΡΡΡ), Π³ΡΠ°Ρ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ, ΠΏΡΠ» ΠΏΠΎΡΠΎΠΊΠΎΠ² = ΡΠΈΡΠ»Ρ ΡΠ΄Π΅Ρ, ΠΏΠΎΡΠΎΠΊΠΎΠ±Π΅Π·ΠΎΠΏΠ°ΡΠ½Π°Ρ ΠΎΡΠ΅ΡΠ΅Π΄Ρ, Π°Π²ΡΠΎΡΠ°Π·Π±ΠΈΠ΅Π½ΠΈΠ΅ ParallelFor.
ΠΠ΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΡ Π΄Π°Π½Π½ΡΡ
: Π°ΡΠΎΠΌΠ°ΡΠ½ΡΠ΅ ΡΠΈΠΏΡ, ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΡ Ρ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡΠΌ Π΄ΠΎΡΡΡΠΏΠΎΠΌ (Π°Π½Π°Π»ΠΎΠ³ NativeContainer
/NativeArray
).
ΠΡΠΈΠΌΠ΅ΡΡ:
#include "Jobs/JobSystem.hpp"
#include "Jobs/JobHandle.hpp"
class MyJob : public Jobs::iJob {
public:
void Execute() override {}
std::vector<Jobs::JobHandle> GetDependencies() override { return {}; }
};
void runMassiveJobSchedulingExample() {
auto& jobSystem = Jobs::JobSystem::GetInstance();
std::vector<Jobs::JobHandle> handles; handles.reserve(100000);
for (int i = 0; i < 100000; ++i) {
auto job = std::make_unique<MyJob>();
handles.push_back(jobSystem.Schedule(std::move(job)));
}
for (const auto& h : handles) { h.Complete(); }
}
ΠΠ»ΡΠ±ΠΎΠΊΠ°Ρ ΡΠ΅ΠΏΠΎΡΠΊΠ° Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ:
void testDeepDependencyChain(int depth) {
Jobs::JobHandle lastHandle;
for (int i = 0; i < depth; ++i) {
auto job = std::make_unique<MyJob>();
lastHandle = Jobs::JobSystem::GetInstance().Schedule(std::move(job), lastHandle);
}
lastHandle.Complete();
}
ParallelFor:
class MyParallelForJob : public Jobs::iJobParallelFor {
public:
std::vector<int> data; MyParallelForJob(size_t size) : data(size) {}
void Execute(int p_index) override { data[p_index] = p_index * 2; }
};
void runParallelForExample() {
auto job = std::make_unique<MyParallelForJob>(100000);
auto& js = Jobs::JobSystem::GetInstance();
Jobs::JobHandle h = js.Schedule(std::move(job));
h.Complete();
}
03.09.2025 β ECS: v1.0.0
π ECS-Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° β ΠΊΠ»ΠΎΠ½ API Unity DOTS Π½Π° ΡΠΈΡΡΠΎΠΌ C++.
Core: ΡΡΡΠ½ΠΎΡΡΠΈ (ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΡ), ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ (ΡΡΡΡΠΊΡΡΡΡ), ΡΠΈΡΡΠ΅ΠΌΡ (Π»ΠΎΠ³ΠΈΠΊΠ° Π½Π°Π΄ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°ΠΌΠΈ).
ΠΡΡΠΏΠΏΡ ΠΈ Π΄Π΅ΠΊΠ»Π°ΡΠ°ΡΠΈΠΈ:
UpdateInGroup<...>
Π΄Π»Ρ ΠΏΠΎΡΡΠ΄ΠΊΠ° Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ,Any<...>
,Frequency<...>
.- ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ ΡΠ΅Π·ΠΎΠ»Π²ΠΈΠ½Π³ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΠΎΠ²
Update(...)
ΠΏΠΎΠ΄ Π½ΡΠΆΠ½ΡΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ ΠΈ ΠΏΠ΅ΡΠ΅Π³ΡΡΠ·ΠΊΠΈ. - ΠΡΠΊΠ»ΡΡΠ°ΡΡΠΈΠ΅ Π·Π°ΠΏΡΠΎΡΡ ΡΠ΅ΡΠ΅Π·
Exclude<...>
.
EntityQuery: Π΄Π΅ΠΊΠ»Π°ΡΠ°ΡΠΈΠ²Π½ΡΠ΅ Π·Π°ΠΏΡΠΎΡΡ Ρ With/Without
, ΠΈΡΠ΅ΡΠ°ΡΠΈΡ ΠΈ Each(...)
.
Π Π°ΡΡΠΈΡΠ΅Π½Π½ΡΠ΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈ: DynamicBuffer<T>
, EntityCommandBuffer
, SharedComponent<T>
, ΡΠ΅Π°ΠΊΡΠΈΠ²Π½ΡΠ΅ ΡΠΈΡΡΠ΅ΠΌΡ, LinkedEntityGroup
.
ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Ρ Godot:
ΠΠΎΠ»Π½Π°Ρ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ Π΄Π°Π½Π½ΡΡ ΠΌΠ΅ΠΆΠ΄Ρ ECS-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°ΠΌΠΈ (ΠΏΠΎΠ·ΠΈΡΠΈΡ, Π²ΡΠ°ΡΠ΅Π½ΠΈΠ΅, ΠΌΠ°ΡΡΡΠ°Π± ΠΈ Ρ. ΠΏ.) ΠΈ ΡΠ·Π»Π°ΠΌΠΈ Godot. Godot β Π²ΠΈΠ·ΡΠ°Π»ΠΈΠ·Π°ΡΠΈΡ (UI/ΡΠ΅Π½Π΄Π΅Ρ/Π°ΡΠ΄ΠΈΠΎ), ECS (C++) β Π»ΠΎΠ³ΠΈΠΊΠ°/Π΄Π°Π½Π½ΡΠ΅.
24.09.2025 β Π Π΅Π½Π΄Π΅Ρ, Π°ΡΡΠ΅ΡΡ, UI ΠΈ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ°
ΠΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½ Π½Π° Vulkan
- ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ:
Render
ΠΈRenderGraph
. - Π‘ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½Π°Ρ, Π±ΡΡΡΡΠ°Ρ ΠΈ Π³ΠΈΠ±ΠΊΠ°Ρ ΠΎΡΠ½ΠΎΠ²Π° Π΄Π»Ρ ΡΡΠΆΡΠ»ΡΡ ΡΡΠ΅Π½.
ΠΠΎΠ΄ΡΠ»ΡΠ½Π°Ρ ΡΠΈΡΡΠ΅ΠΌΠ° Π°ΡΡΠ΅ΡΠΎΠ²
TextureAsset
,ShaderAsset
,MaterialAsset
,MeshAsset
(.gltf
). Π Π°ΡΡΠΈΡΡΠ΅ΠΌΠ°Ρ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ° Π΄Π»Ρ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΡ ΡΠΈΠΏΠΎΠ².
UI Π½Π° Π²Π΅Π±-ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΡΡ ΠΈ ΠΌΠΎΡΡ C++ β TypeScript
- ΠΠ΅ΡΠ΅Ρ ΠΎΠ΄ Ρ CEF Π½Π° Ultralight (Π»ΡΠ³ΠΊΠΈΠΉ ΠΈ Π±ΡΡΡΡΡΠΉ).
- ΠΠ΅ΡΠΊΠ°Π»ΡΠ½ΡΠΉ ECS API: ΠΊΠΎΠ΄ Π½Π° TS ΠΏΠΎΠ²ΡΠΎΡΡΠ΅Ρ C++ ΠΏΠΎΡΡΠΈ 1-Π²-1 (Π²ΠΊΠ»ΡΡΠ°Ρ
EntityQuery
). - ΠΠ΄ΠΈΠ½Π°Ρ ΡΠΊΠΎΡΠΈΡΡΠ΅ΠΌΠ°: ΠΎΠ±ΡΠΈΠΉ ΡΡΠ΅ΠΊ Π΄Π»Ρ ΡΠ΅Π΄Π°ΠΊΡΠΎΡΠ°, ΠΈΠ³ΡΡ ΠΈ ΡΠ°ΠΉΡΠ° (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Nuxt 4 + TypeScript).
Π’ΡΡΡ ΡΠ»ΠΎΠΉΠ½Π°Ρ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ°
ΠΡΠ΄Π΅Π»ΡΠ½ΡΠ΅ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΈ Π½Π° ΡΡΠΈ ΡΠ»ΠΎΡ:
- ΠΠΈΠ·ΠΊΠΎΡΡΠΎΠ²Π½Π΅Π²ΡΠΉ: ΠΎΠΊΠ½Π° ΠΠ‘, Π³ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ API (Vulkan ΠΈ Π°Π»ΡΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π°).
- Π―Π΄ΡΠΎ: ECS, Π°ΡΡΠ΅ΡΡ ΠΈ Π±Π°Π·ΠΎΠ²ΡΠ΅ ΠΌΠΎΠ΄ΡΠ»ΠΈ.
- ΠΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΠΉ ΠΏΡΠΎΠ΅ΠΊΡ: ΠΈΠ³ΡΠΎΠ²ΠΎΠΉ ΠΊΠΎΠ΄.
Π€ΠΎΠΊΡΡ Π΄Π°Π»ΡΡΠ΅ β ΡΠ΅Π΄Π°ΠΊΡΠΎΡ Π² Π΄ΡΡ Π΅ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ° Blender (ΠΌΠΎΠ΄ΡΠ»ΡΠ½ΠΎΡΡΡ, ΡΠ°Π±ΠΎΡΠΈΠ΅ ΠΎΠ±Π»Π°ΡΡΠΈ/Workspaces, ΡΠ°ΡΡΠΈΡΡΠ΅ΠΌΠΎΡΡΡ).
ΠΠΎΡΠΎΠΆΠ½Π°Ρ ΠΊΠ°ΡΡΠ° ΡΠ΅Π½Π΄Π΅ΡΠ°
- Anti-aliasing, ΡΠ΅Π½ΠΈ, ΡΡΠ΅ΠΊ ΠΏΠΎΡΡ-ΡΡΡΠ΅ΠΊΡΠΎΠ² (Bloom, Color Grading, SSAO ΠΈ Π΄Ρ.).
- GPU-ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³ UI Π½Π°ΠΏΡΡΠΌΡΡ Π½Π° Vulkan (ΠΈΠ΄Π΅Π°Π»ΡΠ½ΠΎ Π³Π»Π°Π΄ΠΊΠΈΠΉ ΡΠ΅ΠΊΡΡ, ΡΠ°Π·Π³ΡΡΠ·ΠΊΠ° CPU).
- ΠΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΡΠΉ Π΄Π°ΡΠ°-ΠΎΡΠΈΠ΅Π½ΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½ ΡΠ΅Π½Π΄Π΅ΡΠ° ΠΊΠ°ΠΊ Π°Π»ΡΡΠ΅ΡΠ½Π°ΡΠΈΠ²Π° ΠΠΠ-ΡΠ΅Π½Π΄Π΅ΡΡ.
ΠΡΠΈΠΌΠ΅ΡΡ Π·Π΅ΡΠΊΠ°Π»ΡΠ½ΠΎΠ³ΠΎ API ΡΠΈΡΡΠ΅ΠΌ C++ β TS
SpinSystem (Π²ΡΠ°ΡΠ΅Π½ΠΈΠ΅ ΡΡΡΠ½ΠΎΡΡΠΈ):
class SpinSystem : public iSystem<
Sorting<UpdateInGroup<DrawRenderSystemGroup>, UpdateAfter<RenderSystem>>,
Filter<With<AngularVelocity, Rotation>>,
Fps<30>> {
public:
void Update(double dt, const SystemState& s, Entity e,
const AngularVelocity& av, Rotation& r) {
Math::quat dq = Math::quat(av.value * static_cast<float>(dt));
r.value = glm::normalize(r.value * dq);
}
};
class SpinSystem extends iSystem(
Sorting(UpdateInGroup(DrawRenderSystemGroup), UpdateAfter(RenderSystem)),
Filter(With(AngularVelocity, Rotation)),
Fps(30)
) {
override Update(dt: number, s: SystemState, e: Entity,
av: AngularVelocity, r: Rotation): void {
const delta = glm.quat.create();
const axis = glm.vec3.create();
glm.vec3.normalize(axis, av.value);
const angle = glm.vec3.length(av.value) * dt;
glm.quat.setAxisAngle(delta, axis, angle);
glm.quat.multiply(r.value, r.value, delta);
glm.quat.normalize(r.value, r.value);
}
}
UI-ΠΏΡΠΈΠΌΠ΅Ρ (UnitBarsSystem):
const BAR_CONTAINER_ID = 'unit-bar-container';
export class UnitBarsSystem extends iSystem(
Sorting(UpdateInGroup(UISystemGroup)),
Filter(With()),
Frequency(30)
) {
private m_barsMap = new Map<Entity, HTMLElement>();
private m_container: HTMLElement | null = null;
private m_entityBarsQueryFilter: EntityQueryFilter | null = null;
override OnCreate(systemState: SystemState): void {
this.m_container = document.getElementById(BAR_CONTAINER_ID);
this.m_entityBarsQueryFilter = new EntityQuery().With(ScreenPosition).Build();
}
override Update(deltaTime: number, systemState: SystemState): void {
const view = new EntityView(systemState.entityManager, this.m_entityBarsQueryFilter!);
const it: EntityIterator = view.getIterator();
const active = new Set<Entity>();
while (it.next()) {
const id = it.entity; active.add(id);
if (!this.m_barsMap.has(id)) {
const bar = document.createElement('div');
bar.className = 'unit-bar';
this.m_container?.appendChild(bar);
this.m_barsMap.set(id, bar);
}
const bar = this.m_barsMap.get(id)!;
const screenPos = it.components[0];
bar.style.transform = `translate(${screenPos.x}px, ${screenPos.y}px)`;
}
for (const [id, bar] of this.m_barsMap.entries()) {
if (!active.has(id)) { bar.remove(); this.m_barsMap.delete(id); }
}
}
override OnDestroy(): void {
if (this.m_container) this.m_container.innerHTML = '';
this.m_barsMap.clear();
}
}