這幾天打算跟朋友做一個三消類的遊戲,我們計劃用Unity 開發 C# + XLua,在網上找了一天的好的框架 看了ET 等,總感覺不太順手,打算從0開始自己搞一套基於ECS的遊戲框架,ECS 基於 Entitas https://github.com/sschmid/Entitas-CSharp.git
ECS 是 Entity Component System 的簡稱
1. Entitas.IComponent, 我們的組件要繼承這個類, 組件只用於存儲數據
2. Systems
- ReactiveSystem 反應系統,下面是官方解釋,在有數據變化時會觸發,我們需要重寫 觸發器,篩選器,執行
/// A ReactiveSystem calls Execute(entities) if there were changes based on
/// the specified Collector and will only pass in changed entities.
/// A common use-case is to react to changes, e.g. a change of the position
/// of an entity to update the gameObject.transform.position
/// of the related gameObject.
public class LogSystem : ReactiveSystem<GameEntity>
{
public LogSystem(Contexts contexts) : base(contexts.game)
{
}
protected override ICollector<GameEntity> GetTrigger(IContext<GameEntity> context)
{
return context.CreateCollector(GameMatcher.HelloWordLog);
}
protected override bool Filter(GameEntity entity)
{
return entity.hasHelloWordLog;
}
protected override void Execute(List<GameEntity> entities)
{
foreach (var entity in entities)
{
Debug.Log(entity.helloWordLog.message);
}
}
}
-
IInitializeSystem 初始化系統 會執行一次初始化操作 例如我們初始化的時候創建了一個Entity,掛在上HelloWordLog組件,這個時候我們的創建的 ReactiveSystem 就會 調用收集,然後執行,這時候就打印出了 entity的 log組件上的 message
public class InitSystem : IInitializeSystem { private GameContext _gameContext; public InitSystem(Contexts contexts) { _gameContext = contexts.game; } public void Initialize() { _gameContext.CreateEntity().AddHelloWordLog("HelloWord"); } }
-
Feature 特性, 將不同的System添加到Feature以組成新的特性
public class AddGameSystem : Feature { public AddGameSystem(Contexts contexts) : base("AddHelloWordSystem") { Add(new LogSystem(contexts)); Add(new InitSystem(contexts)); } }
- Entitas的啓動 我們創建新的特性,然後初始化這時候會調用到上面定義的IInitializeSystem 系統
public class GameController : MonoBehaviour { public Systems _systems; // Start is called before the first frame update void Start() { var context = Contexts.sharedInstance; _systems = new Feature("Systems").Add(new AddGameSystem(context)); _systems.Initialize(); } // Update is called once per frame void Update() { _systems.Execute(); _systems.Cleanup(); } }