公司要求使用ECS框架经行开发,没办法只能自己学习了。记录一下学习过程。
框架的含义可以去其他地方查看,我这里写一点我的理解(新人,不对请谅解)。ECS即Entity-Component-System(实体-组件-系统) 的缩写。它做到了行为、数据分开,Component存数据。Entity用来就是由各个Component组成。System用来经行他们中间的通信。对于网上或者官方说速度更快、更容易重构代码的说法我都没有体验到,新人,算了经行讲解吧。
版本:unity5.6.6f2(2018.x中已集成该插件直接倒入,理论上也可以按我的方法实现,没试过)
Entitas1.13
官方HelloWorld案例:https://github.com/sschmid/Entitas-CSharp/wiki/Unity-Tutorial-Hello-World
插件下载地址:https://github.com/sschmid/Entitas-CSharp/releases
下载ENtitas.zip解压,有两个文件夹DesperateDevs和Entitas倒入unity中,会多一个Tools菜单选项,点击Preferences或快捷键Ctrl+Shift+J会出现框架配置界面。
点击AutoImport经行一下默认配置,ProjectPath填写自己工程名字+.csproj(我自己填写的ECS_MoveDemo.csproj),Contextsz中需要序列化的关键字,默认有Game和Input。对于一些有自己需要的序列化可以在这里添加。点击Generate经行配置。
成功过后会多一个Generated的文件夹。
Hellowworld案例:
1、创建一个数据脚本DebugMessageComponent.cs
using Entitas; [Game] public class DebugMessageComponent : IComponent { public string message; }
2、创建一个系统DebugMessageSystem.cs用来监听message的值,我的理解类似事件吧
using System.Collections.Generic; using Entitas; using UnityEngine; public class DebugMessageSystem : ReactiveSystem{ public DebugMessageSystem(Contexts contexts) : base(contexts.game) { } protected override ICollector GetTrigger(IContext context) { return context.CreateCollector(GameMatcher.DebugMessage); } protected override bool Filter(GameEntity entity) { return entity.hasDebugMessage; } protected override void Execute(List entities) { foreach (var e in entities) { Debug.Log(e.debugMessage.message); } } }
3、创建赋值初始化系统HelloWorldSystem.cs,恩恩恩,就是现在还需要一个赋值操作,毕竟message现在是null
using Entitas; public class HelloWorldSystem : IInitializeSystem { readonly GameContext _context; public HelloWorldSystem(Contexts contexts) { _context = contexts.game; } public void Initialize() { _context.CreateEntity().AddDebugMessage("Hello World!"); } }
4、同时我们还想让他监听鼠标按下,所以创建LogMouseClickSystem.cs,理解的话也是赋值操作
public class LogMouseClickSystem : IExecuteSystem { readonly GameContext _context; public LogMouseClickSystem(Contexts contexts) { _context = contexts.game; } public void Execute() { if (Input.GetMouseButtonDown(0)) { _context.CreateEntity().AddDebugMessage("Left Mouse Button Clicked"); } if (Input.GetMouseButtonDown(1)) { _context.CreateEntity().AddDebugMessage("Right Mouse Button Clicked"); } } }
5、在鼠标点击时,每一次都会创建一个实体,我们需要销毁它经行第一步的优化,创建CleanupDebugMessageSystem.cs
using Entitas; public class CleanupDebugMessageSystem : ICleanupSystem { readonly GameContext _context; readonly IGroup_debugMessages; public CleanupDebugMessageSystem(Contexts contexts) { _context = contexts.game; _debugMessages = _context.GetGroup(GameMatcher.DebugMessage); } public void Cleanup() { foreach (var e in _debugMessages.GetEntities()) { e.Destroy(); } } }
6、现在各个功能都实现了,我们需要创建这些类的实例即这个类的对象,所以创建TutorialSystems.cs
using Entitas; public class TutorialSystems : Feature { public TutorialSystems(Contexts contexts) : base ("Tutorial Systems") { Add(new HelloWorldSystem(contexts)); Add(new LogMouseClickSystem(contexts)); Add(new DebugMessageSystem(contexts)); Add(new CleanupDebugMessageSystem(contexts)); } }
7、这时我们大部分功能都完成了,需要和Unity经行关联起来创建GameController.cs
using Entitas; using UnityEngine; public class GameController : MonoBehaviour { Systems _systems; void Start() { var contexts = Contexts.sharedInstance; _systems = new Feature("Systems").Add(new TutorialSystems(contexts)); _systems.Initialize(); } void Update() { _systems.Execute(); _systems.Cleanup(); } }
8、终于完成了这个过程,在unity创建一个空物体,将GameController.cs组件添加到这个空物体运行就可以看到效果了
下边是我对Entitas中的类理解。
IInitializeSystem 在开始前执行一次system.Initialize()。通常初始化时经行数据的赋值。类似Start()
IExecuteSystem 执行每一帧system.Execute()。常用来执行每帧改变数据。类似Update()
ICleanupSystem 在其他系统完成后执行每一帧system.Cleanup()通常执行销毁实体功能。类似LeteUpdate()
ITearDownSystem结束后执行一次system.TearDown()。类似OnDestroy()
ReactiveSystem