Documentation

Ecs Overview

Π’ этом Ρ€Π°Π·Π΄Π΅Π»Π΅ прСдставлСн ΠΎΠ±Π·ΠΎΡ€ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ Entity-Component-System (ECS) Π² Wudgine.

Π§Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ ECS?

Entity-Component-System (ECS) β€” это Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π½Ρ‹ΠΉ ΠΏΠ°Ρ‚Ρ‚Π΅Ρ€Π½, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ раздСляСт Π»ΠΎΠ³ΠΈΠΊΡƒ ΠΈ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ³Ρ€Ρ‹ Π½Π° Ρ‚Ρ€ΠΈ основных элСмСнта:

Entity (Π‘ΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ)

Π£Π½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€, ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π² ΠΈΠ³Ρ€ΠΎΠ²ΠΎΠΌ ΠΌΠΈΡ€Π΅. Π‘ΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ сама ΠΏΠΎ сСбС Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΠ»ΠΈ повСдСния.

Component (ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚)

ΠšΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ Π΄Π°Π½Π½Ρ‹Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ прикрСпляСтся ΠΊ сущностям. ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ содСрТат Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΄Π°Π½Π½Ρ‹Π΅, Π½ΠΎ Π½Π΅ Π»ΠΎΠ³ΠΈΠΊΡƒ.

System (БистСма)

Π›ΠΎΠ³ΠΈΠΊΠ°, которая ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ сущности с ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ. БистСмы содСрТат Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅, Π½ΠΎ Π½Π΅ Π΄Π°Π½Π½Ρ‹Π΅.

ΠŸΡ€Π΅ΠΈΠΌΡƒΡ‰Π΅ΡΡ‚Π²Π° ECS

  • ΠšΠΎΠΌΠΏΠΎΠ·ΠΈΡ†ΠΈΡ вмСсто наслСдования: ΠžΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ ΡΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ ΠΏΡƒΡ‚Π΅ΠΌ комбинирования ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ²
  • Π Π°Π·Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Π»ΠΎΠ³ΠΈΠΊΠΈ: Π£Π»ΡƒΡ‡ΡˆΠ°Π΅Ρ‚ ΠΎΡ€Π³Π°Π½ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΊΠΎΠ΄Π° ΠΈ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ
  • ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Π°Ρ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ°: БистСмы ΠΌΠΎΠ³ΡƒΡ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎ с Ρ€Π°Π·Π½Ρ‹ΠΌΠΈ Π³Ρ€ΡƒΠΏΠΏΠ°ΠΌΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ²
  • Кэш-ΡΡ„Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ: Π”Π°Π½Π½Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² хранятся Π² Π½Π΅ΠΏΡ€Π΅Ρ€Ρ‹Π²Π½Ρ‹Ρ… массивах
  • Π“ΠΈΠ±ΠΊΠΎΡΡ‚ΡŒ: Π›Π΅Π³ΠΊΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΡ‚ΡŒ, ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ ΠΈ ΠΈΠ·ΠΌΠ΅Π½ΡΡ‚ΡŒ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ²

АрхитСктура ECS Π² Wudgine

Бущности (Entities)

Π’ Wudgine сущности прСдставлСны ΠΊΠ°ΠΊ простыС ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€Ρ‹:

// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ сущности
Entity player = world.createEntity("Player");

// ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° валидности сущности
if (player.isValid()) {
    // Π Π°Π±ΠΎΡ‚Π° с ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒΡŽ
}

// Π£Π½ΠΈΡ‡Ρ‚ΠΎΠΆΠ΅Π½ΠΈΠ΅ сущности
world.destroyEntity(player);

ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ (Components)

ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ β€” это структуры Π΄Π°Π½Π½Ρ‹Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΈΠΊΡ€Π΅ΠΏΠ»ΡΡ‚ΡŒ ΠΊ сущностям:

// ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°
struct TransformComponent {
    Vector3 position = Vector3(0.0f);
    Quaternion rotation = Quaternion::identity();
    Vector3 scale = Vector3(1.0f);
};

// Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΊ сущности
auto& transform = player.addComponent<TransformComponent>();
transform.position = Vector3(0.0f, 1.0f, 0.0f);

// ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°
if (player.hasComponent<TransformComponent>()) {
    auto& transform = player.getComponent<TransformComponent>();
    transform.position.y += 1.0f;
}

// Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°
player.removeComponent<TransformComponent>();

БистСмы (Systems)

БистСмы ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ сущности с ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ:

// ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ систСмы
class MovementSystem : public System {
public:
    void update(float deltaTime) override {
        // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° всСх сущностСй с ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ Transform ΠΈ Velocity
        world.each<TransformComponent, VelocityComponent>(
            [deltaTime](Entity entity, TransformComponent& transform, VelocityComponent& velocity) {
                transform.position += velocity.value * deltaTime;
            }
        );
    }
};

// РСгистрация систСмы
world.registerSystem<MovementSystem>();

Π–ΠΈΠ·Π½Π΅Π½Π½Ρ‹ΠΉ Ρ†ΠΈΠΊΠ» ECS

  1. Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ: Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΌΠΈΡ€Π°, рСгистрация ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈ систСм
  2. ОбновлСниС: Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ систСм Π² ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠΌ порядкС
  3. Π—Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅: ОсвобоТдСниС рСсурсов ΠΈ ΡƒΠ½ΠΈΡ‡Ρ‚ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΈΡ€Π°
// Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ
World world;
world.registerComponent<TransformComponent>();
world.registerComponent<VelocityComponent>();
world.registerSystem<MovementSystem>();
world.registerSystem<RenderSystem>();

// Π˜Π³Ρ€ΠΎΠ²ΠΎΠΉ Ρ†ΠΈΠΊΠ»
while (game.isRunning()) {
    float deltaTime = timer.getDeltaTime();
    
    // ОбновлСниС всСх систСм
    world.update(deltaTime);
    
    // Π Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³
    renderer.render();
}

// Π—Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅
world.destroy();

Запросы ΠΈ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹

Wudgine прСдоставляСт ΠΌΠΎΡ‰Π½Ρ‹ΠΉ API для запросов сущностСй с ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ:

// ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ всСх сущностСй с ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ Transform ΠΈ Renderer
world.each<TransformComponent, MeshRendererComponent>(
    [](Entity entity, TransformComponent& transform, MeshRendererComponent& renderer) {
        // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° сущности
    }
);

Бобытия ΠΈ сообщСния

Wudgine Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ систСму событий для ΠΊΠΎΠΌΠΌΡƒΠ½ΠΈΠΊΠ°Ρ†ΠΈΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ систСмами:

// ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ события
struct CollisionEvent {
    Entity entityA;
    Entity entityB;
    Vector3 contactPoint;
    Vector3 contactNormal;
};

// ΠžΡ‚ΠΏΡ€Π°Π²ΠΊΠ° события
world.emit<CollisionEvent>({player, enemy, contactPoint, contactNormal});

// Подписка Π½Π° событиС
world.subscribe<CollisionEvent>([](const CollisionEvent& event) {
    // ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° события столкновСния
    Debug::log("Collision between {} and {}", 
        event.entityA.getName(), 
        event.entityB.getName());
});

БСриализация

Wudgine ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΡΠ΅Ρ€ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΈ Π΄Π΅ΡΠ΅Ρ€ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ сущностСй ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ²:

// БСриализация сущности Π² JSON
Entity player = world.createEntity("Player");
player.addComponent<TransformComponent>();
player.addComponent<PlayerComponent>();

json playerJson = EntitySerializer::toJson(player);

// ДСсСриализация сущности ΠΈΠ· JSON
Entity loadedPlayer = EntitySerializer::fromJson(world, playerJson);

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ шаги

Π’Π΅ΠΏΠ΅Ρ€ΡŒ, ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ ознакомились с основами ECS Π² Wudgine, Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅ΠΌ:

ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹

Π˜Π·ΡƒΡ‡ΠΈΡ‚Π΅ встроСнныС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈ созданиС ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΡ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ².

БистСмы

Π£Π·Π½Π°ΠΉΡ‚Π΅ большС ΠΎ систСмах ΠΈ ΠΈΡ… ΠΆΠΈΠ·Π½Π΅Π½Π½ΠΎΠΌ Ρ†ΠΈΠΊΠ»Π΅.

Wudgine β€’ Β© 2025