Unclaimed Package Is this your package? Claim it to unlock full analytics and manage your listing.
Claim This Package

Install via UPM

Add to Unity Package Manager using this URL

https://www.pkglnk.dev/leopotam-ecs.git

README Markdown

Copy this to your project's README.md

Style
Preview
pkglnk installs badge
## Installation

Add **LeoECS Core** to your Unity project via Package Manager:

1. Open **Window > Package Manager**
2. Click **+** > **Add package from git URL**
3. Enter:
```
https://www.pkglnk.dev/leopotam-ecs.git
```

[![pkglnk](https://www.pkglnk.dev/badge/leopotam-ecs.svg?style=pkglnk)](https://www.pkglnk.dev/pkg/leopotam-ecs)

README

LeoECS - ЛСгковСсный C# Entity Component System Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ

ΠŸΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ, Π½ΡƒΠ»Π΅Π²Ρ‹Π΅ ΠΈΠ»ΠΈ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Π΅ Π°Π»Π»ΠΎΠΊΠ°Ρ†ΠΈΠΈ, минимизация использования памяти, отсутствиС зависимостСй ΠΎΡ‚ любого ΠΈΠ³Ρ€ΠΎΠ²ΠΎΠ³ΠΎ Π΄Π²ΠΈΠΆΠΊΠ° - это основныС Ρ†Π΅Π»ΠΈ Π΄Π°Π½Π½ΠΎΠ³ΠΎ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠ°.

Π’ΠΠ–ΠΠž! Π ΠΠ—Π ΠΠ‘ΠžΠ’ΠšΠ Π”ΠΠΠΠžΠ“Πž ΠŸΠ ΠžΠ•ΠšΠ’Π ΠŸΠ Π•ΠšΠ ΠΠ©Π•ΠΠ, Π’ΠœΠ•Π‘Π’Πž ΠΠ•Π“Πž Π‘Π›Π•Π”Π£Π•Π’ Π˜Π‘ΠŸΠžΠ›Π¬Π—ΠžΠ’ΠΠ’Π¬ EcsProto, Π»ΠΈΠ±ΠΎ EcsLite.

Π’ΠΠ–ΠΠž! НС Π·Π°Π±Ρ‹Π²Π°ΠΉΡ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ DEBUG-вСрсии Π±ΠΈΠ»Π΄ΠΎΠ² для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΈ RELEASE-вСрсии Π±ΠΈΠ»Π΄ΠΎΠ² для Ρ€Π΅Π»ΠΈΠ·ΠΎΠ²: всС Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ/ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ Π±ΡƒΠ΄ΡƒΡ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² DEBUG-вСрсиях ΠΈ ΡƒΠ΄Π°Π»Π΅Π½Ρ‹ для увСличСния ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Π² RELEASE-вСрсиях.

Π’ΠΠ–ΠΠž! LeoEcs-Ρ„Ρ€Π΅ΠΉΠΌΠΎΡ€ΠΊ Π½Π΅ потокобСзопасСн ΠΈ Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ Ρ‚Π°ΠΊΠΈΠΌ! Если Π²Π°ΠΌ Π½ΡƒΠΆΠ½Π° ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΡ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ - Π²Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π΅ ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈ ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·Π°Ρ†ΠΈΡŽ Π² Π²ΠΈΠ΄Π΅ ecs-систСмы.

Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠ°Π½ΠΈΠ΅

Π‘ΠΎΡ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Π΅ рСсурсы

Π‘Π»ΠΎΠ³ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°

Установка

Π’ Π²ΠΈΠ΄Π΅ unity модуля

ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ΡΡ установка Π² Π²ΠΈΠ΄Π΅ unity-модуля Ρ‡Π΅Ρ€Π΅Π· git-ссылку Π² PackageManager ΠΈΠ»ΠΈ прямоС Ρ€Π΅Π΄Π°ΠΊΡ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Packages/manifest.json:

"com.leopotam.ecs": "https://github.com/Leopotam/ecs.git",

По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ послСдняя рСлизная вСрсия. Если трСбуСтся вСрсия "Π² Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅" с Π°ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΌΠΈ измСнСниями - слСдуСт ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒΡΡ Π½Π° Π²Π΅Ρ‚ΠΊΡƒ develop:

"com.leopotam.ecs": "https://github.com/Leopotam/ecs.git#develop",

Π’ Π²ΠΈΠ΄Π΅ исходников

Код Ρ‚Π°ΠΊ ΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ склонирован ΠΈΠ»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ Π² Π²ΠΈΠ΄Π΅ Π°Ρ€Ρ…ΠΈΠ²Π° со страницы Ρ€Π΅Π»ΠΈΠ·ΠΎΠ².

ΠžΡΠ½ΠΎΠ²Π½Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹

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

ЯвляСтся ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠΌ для Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ ΠΈ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ Π»ΠΎΠ³ΠΈΠΊΡƒ (Π΄ΠΎΠΏΡƒΡΠΊΠ°ΡŽΡ‚ΡΡ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Π΅ Ρ…Π΅Π»ΠΏΠ΅Ρ€Ρ‹, Π½ΠΎ Π½Π΅ куски основной Π»ΠΎΠ³ΠΈΠΊΠΈ):

struct WeaponComponent {
    public int Ammo;
    public string GunName;
}

Π‘ΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ

Π‘Π°ΠΌΠ° ΠΏΠΎ сСбС Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π·Π½Π°Ρ‡ΠΈΡ‚ ΠΈ Π½Π΅ сущСствуСт, являСтся ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠΌ для ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ². Π Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° ΠΊΠ°ΠΊ EcsEntity:

// NewEntity() ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для создания Π½ΠΎΠ²Ρ‹Ρ… сущностСй Π² контСкстС ΠΌΠΈΡ€Π°.
EcsEntity entity = _world.NewEntity ();

// Get() Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Π½Π° сущности ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚. Если ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Π½Π΅ сущСствовал - ΠΎΠ½ Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ автоматичСски.
// Π‘Π»Π΅Π΄ΡƒΠ΅Ρ‚ ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° "ref" - ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒΡΡ ΠΏΠΎ ссылкС.
ref Component1 c1 = ref entity.Get<Component1> ();
ref Component2 c2 = ref entity.Get<Component2> ();

// Del() удаляСт ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ с сущности. Если это Π±Ρ‹Π» послСдний ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ - ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ Π±ΡƒΠ΄Π΅Ρ‚ ΡƒΠ΄Π°Π»Π΅Π½Π° автоматичСски. Если ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Π½Π΅ сущСствовал - ошибки Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚.
entity.Del<Component2> ();

// Replace() выполняСт Π·Π°ΠΌΠ΅Π½Ρƒ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° Π½ΠΎΠ²Ρ‹ΠΌ экзСмпляром. Если старый ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Π½Π΅ сущСствовал - Π½ΠΎΠ²Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ Π±Π΅Π· ошибки.
WeaponComponent weapon = new WeaponComponent () { Ammo = 10, GunName = "Handgun" };
entity.Replace (weapon);

// Replace() позволяСт Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ "Ρ‡Π΅ΠΉΠ½ΠΈΠ½Π³" создания ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ²:
EcsEntity entity2 = world.NewEntity ();
entity2.Replace (new Component1 { Id = 10 }).Replace (new Component2 { Name = "Username" });

// Π›ΡŽΠ±Π°Ρ ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ скопирована вмСстС с ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ:
EcsEntity entity2Copy = entity2.Copy ();

// Π›ΡŽΠ±Π°Ρ ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ ΠΌΠΎΠΆΠ΅Ρ‚ "ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ" свои ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Π΄Ρ€ΡƒΠ³ΠΎΠΉ сущности (сама Π±ΡƒΠ΄Π΅Ρ‚ ΡƒΠ½ΠΈΡ‡Ρ‚ΠΎΠΆΠ΅Π½Π°):
var newEntity = world.NewEntity ();
entity2Copy.MoveTo (newEntity); // всС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ с "entity2Copy" пСрСмСстятся Π½Π° "newEntity", Π° "entity2Copy" Π±ΡƒΠ΄Π΅Ρ‚ ΡƒΠ΄Π°Π»Π΅Π½Π°.

// Π›ΡŽΠ±Π°Ρ ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΡƒΠ΄Π°Π»Π΅Π½Π°, ΠΏΡ€ΠΈ этом сначала всС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Π±ΡƒΠ΄ΡƒΡ‚ автоматичСски ΡƒΠ΄Π°Π»Π΅Π½Ρ‹ ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎΡ‚ΠΎΠΌ энтити Π±ΡƒΠ΄Π΅Ρ‚ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒΡΡ ΡƒΠ½ΠΈΡ‡Ρ‚ΠΎΠΆΠ΅Π½Π½ΠΎΠΉ.
entity.Destroy ();

Π’ΠΠ–ΠΠž! Бущности Π½Π΅ ΠΌΠΎΠ³ΡƒΡ‚ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ Π±Π΅Π· ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ автоматичСски ΡƒΠ½ΠΈΡ‡Ρ‚ΠΎΠΆΠ°Ρ‚ΡŒΡΡ ΠΏΡ€ΠΈ ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠΈ послСднСго ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° Π½Π° Π½ΠΈΡ….

БистСма

ЯвляСтся ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠΌ для основной Π»ΠΎΠ³ΠΈΠΊΠΈ для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΎΡ‚Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… сущностСй. БущСствуСт Π² Π²ΠΈΠ΄Π΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΎΠ³ΠΎ класса, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰Π΅Π³ΠΎ ΠΊΠ°ΠΊ ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· IEcsInitSystem, IEcsDestroySystem, IEcsRunSystem (ΠΈ ΠΏΡ€ΠΎΡ‡ΠΈΡ… ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹Ρ…) интСрфСйсов:

class UserSystem : IEcsPreInitSystem, IEcsInitSystem, IEcsRunSystem, IEcsDestroySystem, IEcsPostDestroySystem {
    public void PreInit () {
        // Π‘ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρ‹ EcsSystems.Init() ΠΈ Π΄ΠΎ срабатывания IEcsInitSystem.Init().
    }

    public void Init () {
        // Π‘ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρ‹ EcsSystems.Init() ΠΈ послС срабатывания IEcsPreInitSystem.PreInit().
    }

    public void Run () {
        // Π‘ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρ‹ EcsSystems.Run().
    }

    public void Destroy () {
        // Π‘ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρ‹ EcsSystems.Destroy() ΠΈ Π΄ΠΎ срабатывания IEcsPostDestroySystem.PostDestroy().
    }

    public void PostDestroy () {
        // Π‘ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π·Π²Π°Π½ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρ‹ EcsSystems.Destroy() ΠΈ послС срабатывания IEcsDestroySystem.Destroy().
    }
}

Π˜Π½ΡŠΠ΅ΠΊΡ†ΠΈΡ Π΄Π°Π½Π½Ρ‹Ρ…

ВсС поля ecs-систСм, совмСстимыС c EcsWorld ΠΈ EcsFilter<T> Π±ΡƒΠ΄ΡƒΡ‚ автоматичСски ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ Π²Π°Π»ΠΈΠ΄Π½Ρ‹ΠΌΠΈ экзСмплярами ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… Ρ‚ΠΈΠΏΠΎΠ²:

class HealthSystem : IEcsSystem {
    // Поля с Π°Π²Ρ‚ΠΎ-ΠΈΠ½ΡŠΠ΅ΠΊΡ†ΠΈΠ΅ΠΉ.
    EcsWorld _world;
    EcsFilter<WeaponComponent> _weaponFilter;
}

ЭкзСмпляр любого кастомного Ρ‚ΠΈΠΏΠ° (класса) ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΈΠ½ΡŠΠ΅Ρ†ΠΈΡ€ΠΎΠ²Π°Π½ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° EcsSystems.Inject():

class SharedData {
    public string PrefabsPath;
}
...
SharedData sharedData = new SharedData { PrefabsPath = "Items/{0}" };
EcsSystems systems = new EcsSystems (world);
systems
    .Add (new TestSystem1 ())
    .Inject (sharedData)
    .Init ();

КаТдая систСма Π±ΡƒΠ΄Π΅Ρ‚ просканирована Π½Π° Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ ΠΏΠΎΠ»Π΅ΠΉ, совмСстимых ΠΏΠΎ Ρ‚ΠΈΠΏΡƒ с ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ΠΈΠ½ΡŠΠ΅ΠΊΡ†ΠΈΠ΅ΠΉ:

class TestSystem1 : IEcsInitSystem {
    // ПолС с Π°Π²Ρ‚ΠΎ-ΠΈΠ½ΡŠΠ΅ΠΊΡ†ΠΈΠ΅ΠΉ.
    SharedData _sharedData;

    public void Init() {
        var prefabPath = string.Format (_sharedData.Prefabspath, 123);
        // prefabPath = "Items/123" ΠΊ этому ΠΌΠΎΠΌΠ΅Π½Ρ‚Ρƒ.
    }
}

Π’ΠΠ–ΠΠž! Для ΠΈΠ½ΡŠΠ΅ΠΊΡ†ΠΈΠΈ подходят Ρ‚ΠΎΠ»ΡŒΠΊΠΎ нСстатичныС public/private-поля ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎΠ³ΠΎ класса систСмы, Π»ΠΈΠ±ΠΎ public/protected-поля Π±Π°Π·ΠΎΠ²Ρ‹Ρ… классов. ВсС ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ поля Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹!

Π‘ΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Π΅ Ρ‚ΠΈΠΏΡ‹

EcsFilter

ЯвляСтся ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠΌ для хранСния ΠΎΡ‚Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… сущностСй ΠΏΠΎ Π½Π°Π»ΠΈΡ‡ΠΈΡŽ ΠΈΠ»ΠΈ ΠΎΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΠΈΡŽ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ²:

class WeaponSystem : IEcsInitSystem, IEcsRunSystem {
    // Поля с Π°Π²Ρ‚ΠΎ-ΠΈΠ½ΡŠΠ΅ΠΊΡ†ΠΈΠ΅ΠΉ.
    EcsWorld _world;
    // ΠœΡ‹ Ρ…ΠΎΡ‚ΠΈΠΌ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ всС сущности с ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠΌ "WeaponComponent"
    // ΠΈ Π±Π΅Π· ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° "HealthComponent".
    EcsFilter<WeaponComponent>.Exclude<HealthComponent> _filter;

    public void Init () {
        _world.NewEntity ().Get<WeaponComponent> ();
    }

    public void Run () {
        foreach (int i in _filter) {
            // Π‘ΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ, которая Ρ‚ΠΎΡ‡Π½ΠΎ содСрТит ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ "WeaponComponent".
            ref EcsEntity entity = ref _filter.GetEntity (i);

            // Get1() позволяСт ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ доступ ΠΏΠΎ ссылкС Π½Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚,
            // ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ Π² спискС ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° ("WeaponComponent").
            ref WeaponComponent weapon = ref _filter.Get1 (i);
            weapon.Ammo = System.Math.Max (0, weapon.Ammo - 1);
        }
    }
}

Π›ΡŽΠ±Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈΠ· Include-списка ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Ρ‹ Ρ‡Π΅Ρ€Π΅Π· Π²Ρ‹Π·ΠΎΠ²Ρ‹ EcsFilter.Get1(), EcsFilter.Get2() ΠΈ Ρ‚.Π΄ - нумСрация ΠΈΠ΄Π΅Ρ‚ Π² Ρ‚ΠΎΠΌ ΠΆΠ΅ порядкС, Ρ‡Ρ‚ΠΎ ΠΈ Π² спискС ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ.

Если Π² ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π΅ Π½Π΅Ρ‚ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ ΠΎΠ½ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΠ°ΠΊ Ρ„Π»Π°Π³-ΠΏΡ€ΠΈΠ·Π½Π°ΠΊ для Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠΈ, Ρ‚ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ интСрфСйс IEcsIgnoreInFilter - это ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ ΡƒΠΌΠ΅Π½ΡŒΡˆΠΈΡ‚ΡŒ ΠΏΠΎΡ‚Ρ€Π΅Π±Π»Π΅Π½ΠΈΠ΅ памяти Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠΌ ΠΈ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ:

struct Component1 { }

struct Component2 : IEcsIgnoreInFilter { }

class TestSystem : IEcsRunSystem {
    EcsFilter<Component1, Component2> _filter;

    public void Run () {
        foreach (var i in _filter) {
            // ΠœΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ "Component1".
            ref var component1 = ref _filter.Get1 (i);

            // ΠœΡ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ "Component2" - кСш Π²Π½ΡƒΡ‚Ρ€ΠΈ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° Π½Π΅ сущСствуСт ΠΈ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΊΠΈΠ½ΡƒΡ‚ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅.
            ref var component2 = ref _filter.Get2 (i);
        }
    }
}

Π’ΠΠ–ΠΠž!: Π€ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ Π΄ΠΎ 6 Include-ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ ΠΈ 2 Exclude-ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ. Π§Π΅ΠΌ мСньшС ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ Π² Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π΅ - Ρ‚Π΅ΠΌ ΠΎΠ½ быстрСС Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚.

Π’ΠΠ–ΠΠž! НСльзя ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ нСсколько Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ² с ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹ΠΌ списком ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ, Π½ΠΎ выставлСнных Π² Ρ€Π°Π·Π½ΠΎΠΌ порядкС - Π² DEBUG-вСрсии Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹ΠΊΠΈΠ½ΡƒΡ‚ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ с описаниСм ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ΡƒΡŽΡ‰ΠΈΡ… Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ².

Π’ΠΠ–ΠΠž! Один ΠΈ Ρ‚ΠΎΡ‚ ΠΆΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π² списках "Include" ΠΈ "Exclude" ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π° ΠΎΠ΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ.

EcsWorld

ЯвляСтся ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠΌ для всСх сущностСй ΠΈ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ², Π΄Π°Π½Π½Ρ‹Π΅ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ экзСмпляра ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ ΠΈ ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ ΠΎΡ‚ Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΌΠΈΡ€ΠΎΠ².

Π’ΠΠ–ΠΠž! НСобходимо Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ EcsWorld.Destroy() Ρƒ экзСмпляра ΠΌΠΈΡ€Π° Ссли ΠΎΠ½ большС Π½Π΅ Π½ΡƒΠΆΠ΅Π½.

EcsSystems

ЯвляСтся ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠΌ для систСм, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒΡΡ EcsWorld-экзСмпляр ΠΌΠΈΡ€Π°:

class Startup : MonoBehaviour {
    EcsWorld _world;
    EcsSystems _systems;

    void Start () {
        // Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅, ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ систСмы.
        _world = new EcsWorld ();
        _systems = new EcsSystems (_world)
            .Add (new WeaponSystem ());
        _systems.Init ();
    }

    void Update () {
        // ВыполняСм всС ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½Π½Ρ‹Π΅ систСмы.
        _systems.Run ();
    }

    void OnDestroy () {
        // Π£Π½ΠΈΡ‡Ρ‚ΠΎΠΆΠ°Π΅ΠΌ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡Π΅Π½Π½Ρ‹Π΅ систСмы.
        _systems.Destroy ();
        // ΠžΡ‡ΠΈΡ‰Π°Π΅ΠΌ ΠΎΠΊΡ€ΡƒΠΆΠ΅Π½ΠΈΠ΅.
        _world.Destroy ();
    }
}

ЭкзСмпляр EcsSystems ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использован ΠΊΠ°ΠΊ обычная ecs-систСма (Π²Π»ΠΎΠΆΠ΅Π½Π° Π² Π΄Ρ€ΡƒΠ³ΡƒΡŽ EcsSystems):

// Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ.
EcsSystems nestedSystems = new EcsSystems (_world).Add (new NestedSystem ());

// НСльзя Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ nestedSystems.Init() здСсь,
// "rootSystems" Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ этот Π²Ρ‹Π·ΠΎΠ² автоматичСски.
EcsSystems rootSystems = new EcsSystems (_world).Add (nestedSystems);
rootSystems.Init ();

// Π’ Ρ†ΠΈΠΊΠ»Π΅ обновлСния нСльзя Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ nestedSystems.Run(),
// "rootSystems" Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ этот Π²Ρ‹Π·ΠΎΠ² автоматичСски.
rootSystems.Run ();

// ΠžΡ‡ΠΈΡΡ‚ΠΊΠ°.
// НСльзя Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ nestedSystems.Destroy() здСсь,
// "rootSystems" Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ этот Π²Ρ‹Π·ΠΎΠ² автоматичСски.
rootSystems.Destroy ();

Π›ΡŽΠ±Π°Ρ IEcsRunSystem систСма (Π²ΠΊΠ»ΡŽΡ‡Π°Ρ Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ EcsSystems) ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ ΠΈΠ»ΠΈ Π²Ρ‹ΠΊΠ»ΡŽΡ‡Π΅Π½ ΠΈΠ· списка ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ:

class TestSystem : IEcsRunSystem {
    public void Run () { }
}
EcsSystems systems = new EcsSystems (_world);
systems.Add (new TestSystem (), "my special system");
systems.Init ();
var idx = systems.GetNamedRunSystem ("my special system");

// "state" Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ "true", всС систСмы Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ.
var state = systems.GetRunSystemState (idx);

// Π’Ρ‹ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ систСму ΠΏΠΎ Π΅Π΅ индСксу.
systems.SetRunSystemState (idx, false);

Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡ с Π΄Π²ΠΈΠΆΠΊΠ°ΠΌΠΈ

Unity

ΠŸΡ€ΠΎΠ²Π΅Ρ€Π΅Π½ΠΎ Π½Π° Unity 2020.3 (Π½Π΅ зависит ΠΎΡ‚ Π½Π΅Π΅) ΠΈ содСрТит asmdef-описания для компиляции Π² Π²ΠΈΠ΄Π΅ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… сборок ΠΈ ΡƒΠΌΠ΅Π½ΡŒΡˆΠ΅Π½ΠΈΡ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ рСкомпиляции основного ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°.

Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡ Π² Unity editor содСрТит ΡˆΠ°Π±Π»ΠΎΠ½Ρ‹ ΠΊΠΎΠ΄Π°, Π° Ρ‚Π°ΠΊ ΠΆΠ΅ прСдоставляСт ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³ состояния ΠΌΠΈΡ€Π°.

ΠšΠ°ΡΡ‚ΠΎΠΌΠ½Ρ‹ΠΉ Π΄Π²ΠΈΠΆΠΎΠΊ

Для использования Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠ° трСбуСтся C#7.3 ΠΈΠ»ΠΈ Π²Ρ‹ΡˆΠ΅.

КаТдая Ρ‡Π°ΡΡ‚ΡŒ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π½ΠΈΠΆΠ΅ Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Π½Π° Π² ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅ мСсто выполнСния ΠΊΠΎΠ΄Π° Π΄Π²ΠΈΠΆΠΊΠΎΠΌ:

using Leopotam.Ecs;

class EcsStartup {
    EcsWorld _world;
    EcsSystems _systems;

    // Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ окруТСния.
    void Init () {
        _world = new EcsWorld ();
        _systems = new EcsSystems (_world);
        _systems
            // БистСмы с основной Π»ΠΎΠ³ΠΈΠΊΠΎΠΉ Π΄ΠΎΠ»ΠΆΠ½Ρ‹
            // Π±Ρ‹Ρ‚ΡŒ зарСгистрированы здСсь, порядок Π²Π°ΠΆΠ΅Π½:
            // .Add (new TestSystem1 ())
            // .Add (new TestSystem2 ())

            // OneFrame-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ зарСгистрированы
            // Π² ΠΎΠ±Ρ‰Π΅ΠΌ спискС систСм, порядок Π²Π°ΠΆΠ΅Π½:
            // .OneFrame<TestComponent1> ()
            // .OneFrame<TestComponent2> ()

            // Π˜Π½ΡŠΠ΅ΠΊΡ†ΠΈΡ Π΄ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½Π° здСсь,
            // порядок Π½Π΅ Π²Π°ΠΆΠ΅Π½:
            // .Inject (new CameraService ())
            // .Inject (new NavMeshSupport ())
            .Init ();
    }

    // ΠœΠ΅Ρ‚ΠΎΠ΄ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Π²Ρ‹Π·Π²Π°Π½ ΠΈΠ·
    // основного update-Ρ†ΠΈΠΊΠ»Π° Π΄Π²ΠΈΠΆΠΊΠ°.
    void UpdateLoop () {
        _systems?.Run ();
    }

    // ΠžΡ‡ΠΈΡΡ‚ΠΊΠ°.
    void Destroy () {
        if (_systems != null) {
            _systems.Destroy ();
            _systems = null;
            _world.Destroy ();
            _world = null;
        }
    }
}

Π‘Ρ‚Π°Ρ‚ΡŒΠΈ

ΠŸΡ€ΠΎΠ΅ΠΊΡ‚Ρ‹, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΠ΅ LeoECS

Π‘ исходниками

Π Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡ

ЛицСнзия

Π€Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ выпускаСтся ΠΏΠΎΠ΄ двумя лицСнзиями, подробности Ρ‚ΡƒΡ‚.

Π’ случаях лицСнзирования ΠΏΠΎ условиям MIT-Red Π½Π΅ стоит Ρ€Π°ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ Π½Π° ΠΏΠ΅Ρ€ΡΠΎΠ½Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠΎΠ½ΡΡƒΠ»ΡŒΡ‚Π°Ρ†ΠΈΠΈ ΠΈΠ»ΠΈ ΠΊΠ°ΠΊΠΈΠ΅-Π»ΠΈΠ±ΠΎ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΠΈ.

Π§Π°Π’ΠΎ

Π― Ρ…ΠΎΡ‡Ρƒ Π·Π½Π°Ρ‚ΡŒ - сущСствовал Π»ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Π½Π° сущности Π΄ΠΎ Π²Ρ‹Π·ΠΎΠ²Π° Get() для Ρ€Π°Π·Π½ΠΎΠΉ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ…. Как я ΠΌΠΎΠ³Ρƒ это ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ?

Если Π½Π΅ Π²Π°ΠΆΠ½ΠΎ - сущСствовал ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Ρ€Π°Π½Π΅Π΅ ΠΈ просто Π½ΡƒΠΆΠ½Π° ΡƒΠ²Π΅Ρ€Π΅Π½Π½ΠΎΡΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΎΠ½ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ сущСствуСт достаточно Π²Ρ‹Π·ΠΎΠ²Π° EcsEntity.Get<T>().

Если Π½ΡƒΠΆΠ½ΠΎ ΠΏΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ сущСствовал Ρ€Π°Π½Π΅Π΅ - это ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π²Ρ‹Π·ΠΎΠ²Π° EcsEntity.Has<T>().

Π― Ρ…ΠΎΡ‡Ρƒ ΠΎΠ΄Π½Ρƒ систСму Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ Π² MonoBehaviour.Update(), Π° Π΄Ρ€ΡƒΠ³ΡƒΡŽ - Π² MonoBehaviour.FixedUpdate(). Как я ΠΌΠΎΠ³Ρƒ это ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ?

Для раздСлСния систСм Π½Π° основС Ρ€Π°Π·Π½Ρ‹Ρ… ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² ΠΈΠ· MonoBehaviour Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΏΠΎΠ΄ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ EcsSystems-Π³Ρ€ΡƒΠΏΠΏΡƒ:

EcsSystems _update;
EcsSystems _fixedUpdate;

void Start () {
    var world = new EcsWorld ();
    _update = new EcsSystems (world).Add (new UpdateSystem ());
    _update.Init ();
    _fixedUpdate = new EcsSystems (world).Add (new FixedUpdateSystem ());
    _fixedUpdate.Init ();
}

void Update () {
    _update.Run ();
}

void FixedUpdate () {
    _fixedUpdate.Run ();
}

МнС нравится ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ автоматичСская ΠΈΠ½ΡŠΠ΅ΠΊΡ†ΠΈΡ Π΄Π°Π½Π½Ρ‹Ρ…, Π½ΠΎ Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ Π±Ρ‹ Ρ‡Π°ΡΡ‚ΡŒ ΠΏΠΎΠ»Π΅ΠΉ ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ. Как я ΠΌΠΎΠ³Ρƒ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ это?

Для этого достаточно ΠΏΠΎΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ ΠΏΠΎΠ»Π΅ систСмы Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚ΠΎΠΌ [EcsIgnoreInject]:

// Π­Ρ‚ΠΎ ΠΏΠΎΠ»Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Π½ΠΎ ΠΈΠ½ΡŠΠ΅ΠΊΡ†ΠΈΠ΅ΠΉ.
EcsFilter<C1> _filter1;

// Π­Ρ‚ΠΎ ΠΏΠΎΠ»Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΎΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΎ ΠΈΠ½ΡŠΠ΅ΠΊΡ†ΠΈΠ΅ΠΉ.
[EcsIgnoreInject] EcsFilter<C2> _filter2;

МСня Π½Π΅ ΡƒΡΡ‚Ρ€Π°ΠΈΠ²Π°ΡŽΡ‚ значСния ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для ΠΏΠΎΠ»Π΅ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ². Как я ΠΌΠΎΠ³Ρƒ это Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ?

ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ ΠΊΠ°ΡΡ‚ΠΎΠΌΠ½ΡƒΡŽ настройку Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Ρ‡Π΅Ρ€Π΅Π· Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ интСрфСйса IEcsAutoReset<>:

struct MyComponent : IEcsAutoReset<MyComponent> {
    public int Id;
    public object LinkToAnotherComponent;

    public void AutoReset (ref MyComponent c) {
        c.Id = 2;
        c.LinkToAnotherComponent = null;
    }
}

Π­Ρ‚ΠΎΡ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π±ΡƒΠ΄Π΅Ρ‚ автоматичСски Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒΡΡ для всСх Π½ΠΎΠ²Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², Π° Ρ‚Π°ΠΊ ΠΆΠ΅ для всСх Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Ρ‚ΠΎ ΡƒΠ΄Π°Π»Π΅Π½Π½Ρ‹Ρ…, Π΄ΠΎ помСщСния ΠΈΡ… Π² ΠΏΡƒΠ».

Π’ΠΠ–ΠΠž! Π’ случаС примСнСния IEcsAutoReset всС Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ очистки/ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΏΠΎΠ»Π΅ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ΡΡ, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ ΡƒΡ‚Π΅Ρ‡ΠΊΠ°ΠΌ памяти. ΠžΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π΅Π½Π½ΠΎΡΡ‚ΡŒ Π»Π΅ΠΆΠΈΡ‚ Π½Π° ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅!

Π’ΠΠ–ΠΠž!: ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠ΅ IEcsAutoReset Π½Π΅ совмСстимы с Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ entity.Replace(). РСкомСндуСтся Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ entity.Replace() ΠΈΠ»ΠΈ Π»ΡŽΠ±Ρ‹Π΅ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ способы ΠΏΠΎΠ»Π½ΠΎΠΉ пСрСзаписи ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ².

Π― ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΊΠ°ΠΊ "события", ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΆΠΈΠ²ΡƒΡ‚ 1 Ρ†ΠΈΠΊΠ», Π° ΠΏΠΎΡ‚ΠΎΠΌ ΡƒΠ΄Π°Π»ΡΡŽΡ‚ΡΡ Π² ΠΊΠΎΠ½Ρ†Π΅ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ систСмой. ΠŸΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ΡΡ ΠΌΠ½ΠΎΠ³ΠΎ лишнСго ΠΊΠΎΠ΄Π°, Π΅ΡΡ‚ΡŒ Π»ΠΈ Π±ΠΎΠ»Π΅Π΅ простой способ?

Для автоматичСской очистки ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΆΠΈΡ‚ΡŒ ΠΎΠ΄ΠΈΠ½ Ρ†ΠΈΠΊΠ», мСсто ΠΈΡ… очистки ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ зарСгистрировано Π² ΠΎΠ±Ρ‰Π΅ΠΌ спискС систСм Π²Π½ΡƒΡ‚Ρ€ΠΈ EcsSystems:

struct MyOneFrameComponent { }

EcsSystems _update;

void Start () {
    var world = new EcsWorld ();
    _update = new EcsSystems (world);
    _update
        .Add (new CalculateSystem ())
        // ВсС "MyOneFrameComponent" ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Π±ΡƒΠ΄ΡƒΡ‚
        // ΡƒΠ΄Π°Π»Π΅Π½Ρ‹ здСсь.
        .OneFrame<MyOneFrameComponent> ()
        // Π—Π΄Π΅ΡΡŒ ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ ΡƒΠ²Π΅Ρ€Π΅Π½Π½Ρ‹ΠΌ, Ρ‡Ρ‚ΠΎ Π½ΠΈ ΠΎΠ΄ΠΈΠ½
        // "MyOneFrameComponent" Π½Π΅ сущСствуСт.
        .Add (new UpdateSystem ())
        .Init ();
}

void Update () {
    _update.Run ();
}

МнС Π½ΡƒΠΆΠ΅Π½ больший ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΡŒ Π½Π°Π΄ Ρ€Π°Π·ΠΌΠ΅Ρ€Π°ΠΌΠΈ кСшСй, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΈΡ€ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Π² ΠΌΠΎΠΌΠ΅Π½Ρ‚ создания. Как я ΠΌΠΎΠ³Ρƒ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ это?

ΠœΠΈΡ€ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ создан с явным ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅ΠΌ EcsWorldConfig-ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ:

var config = new EcsWorldConfig () {
    // Π Π°Π·ΠΌΠ΅Ρ€ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для World.Entities.
    WorldEntitiesCacheSize = 1024,
    // Π Π°Π·ΠΌΠ΅Ρ€ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для World.Filters.
    WorldFiltersCacheSize = 128,
    // Π Π°Π·ΠΌΠ΅Ρ€ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для World.ComponentPools.
    WorldComponentPoolsCacheSize = 512,
    // Π Π°Π·ΠΌΠ΅Ρ€ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для Entity.Components (Π΄ΠΎ удвоСния).
    EntityComponentsCacheSize = 8,
    // Π Π°Π·ΠΌΠ΅Ρ€ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для Filter.Entities.
    FilterEntitiesCacheSize = 256,
};
var world = new EcsWorld(config);

МнС Π½ΡƒΠΆΠ½ΠΎ большС Ρ‡Π΅ΠΌ 6-"Include" ΠΈ 2-"Exclude" ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΠΉ для ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² Π² Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π΅. Как я ΠΌΠΎΠ³Ρƒ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ это?

Π’ΠΠ–ΠΠž! Π­Ρ‚ΠΎ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Ρ‚ ΠΊ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ исходного ΠΊΠΎΠ΄Π° Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠ° ΠΈ нСсовмСстимости с обновлСниями.

НСобходимо Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΊΠΎΠ΄ΠΎΠ³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠ΅ΠΉ EcsFilter классов ΠΈ Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ содСрТимоС Ρ„Π°ΠΉΠ»Π° EcsFilter.cs.

Π― Ρ…ΠΎΡ‡Ρƒ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ€Π΅Π°ΠΊΡ‚ΠΈΠ²Ρ‰ΠΈΠ½Ρ‹ ΠΈ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ события измСнСния Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ². Как я ΠΌΠΎΠ³Ρƒ это ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ?

Π’ΠΠ–ΠΠž! Π’Π°ΠΊ Π΄Π΅Π»Π°Ρ‚ΡŒ Π½Π΅ рСкомСндуСтся ΠΈΠ·-Π·Π° падСния ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ.

Для Π°ΠΊΡ‚ΠΈΠ²Π°Ρ†ΠΈΠΈ этого Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»Π° слСдуСт Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ LEOECS_FILTER_EVENTS Π² список Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΈΠ² комплятора, Π° Π·Π°Ρ‚Π΅ΠΌ - Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»ΡŒ событий:

class CustomListener: IEcsFilterListener {
    public void OnEntityAdded (in EcsEntity entity) {
        // Π‘ΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π° Π² Ρ„ΠΈΠ»ΡŒΡ‚Ρ€.
    }

    public void OnEntityRemoved (in EcsEntity entity) {
        // Π‘ΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ ΡƒΠ΄Π°Π»Π΅Π½Π° ΠΈΠ· Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°.
    }
}

class MySystem : IEcsInitSystem, IEcsDestroySystem {
    readonly EcsFilter<Component1> _filter = null;
    readonly CustomListener _listener = new CustomListener ();
    public void Init () {
        // Подписка ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»Ρ Π½Π° события Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°.
        _filter.AddListener (_listener);
    }
    public void Destroy () {
        // ΠžΡ‚ΠΏΠΈΡΠΊΠ° ΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»Ρ ΠΎΡ‚ событий Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°.
        _filter.RemoveListener (_listener);
    }
}

Comments

No comments yet. Be the first!