Unity使用Entitas开发逻辑显示分离Demo(二)
继续上一章说:传送门
目的:
添加完TickUpdateSystem后,我们希望把游戏内的TickCount显示在UI上
那么应该怎么做呢?
思路:
想到添加逻辑的需求,就要添加一个System解决
大体的逻辑就是通过收集游戏所有的TickComponent(这里只有一个),检测逻辑实体变化后,通知所有的 渲染实体
所以
1.先创建一个监听Tick的数据组件:TickListenerComponet
public interface ITickListener
{
void OnTick(int currTick);
}
[Render]
public partial struct TickListenerComponent : IComponent
{
//必须要 public 才能生成代码
public ITickListener listener;
}
2.创建一个负责监听Tick变化通知所有TickListener的系统 NotifyTickListenersSystem
public class NotifyTickListenersSystem : ReactiveSystem<LogicEntity>
{
LogicContext _logicContext;
RenderContext _renderContext;
IGroup<RenderEntity> _listeners;
public NotifyTickListenersSystem(Contexts contexts) : base(contexts.logic)
{
_logicContext = contexts.logic;
_renderContext = contexts.render;
_listeners = _renderContext.GetGroup(RenderMatcher.TickListener);
}
protected override ICollector<LogicEntity> GetTrigger(IContext<LogicEntity> context)
{
return context.CreateCollector(LogicMatcher.Tick);
}
protected override bool Filter(LogicEntity entity)
{
return entity.hasTick;
}
protected override void Execute(List<LogicEntity> entities)
{
int currTick = _logicContext.tick.currentTick;
foreach (var item in _listeners.GetEntities())
{
item.tickListener.listener.OnTick(currTick);
}
}
}
注意:
1.这个是继承 ReactiveSystem ,这个有啥用呢?
可以理解为调用LogicEntity的 ReplaceTick 就可以触发下面的 Excute 函数
有几个回调,是干啥的呢:
Trigger:创建过程调用,收集需要的Entity
Filter:父类Excute中调用,用来过滤Entity群组
Execute:遍历所有的实体,进行数据操作
并且在初始化这个 System
public class ECSTestController : MonoBehaviour
{
private Systems logicSystem;
private Systems renderSystem;
void Start()
{
Contexts contexts = Contexts.sharedInstance;
logicSystem = new Feature("LogicSystem")
.Add(new TickUpdateSystem(contexts));
renderSystem = new Feature("RenderSystem")
.Add(new NotifyTickListenersSystem(contexts));
logicSystem.Initialize();
renderSystem.Initialize();
}
void Update()
{
logicSystem.Execute();
logicSystem.Cleanup();
renderSystem.Execute();
renderSystem.Cleanup();
}
void OnDestroy()
{
logicSystem.TearDown();
renderSystem.TearDown();
}
}
也就是说,我们这个脚本做了2件事:
1.通过 RenderContext 收集所有的 带有TickListenerComponent 的 RenderEntity
2.通过 LogicContext 监听 tick 的变化,并且通知所有的 listener
那么 RenderEntity 如何创建呢?
我们需要先创建一个 UI 的Text,然后给他挂一个脚本
public class TickInfoPanel : MonoBehaviour, ITickListener
{
public Text txt;
void Start()
{
RenderEntity renderEntity = Contexts.sharedInstance.render.CreateEntity();
renderEntity.AddTickListener(this);
}
public void OnTick(int currTick)
{
txt.text = currTick.ToString();
}
}
注意:
1.在 Start 的时候,通过 Contexts 创建了一个 RenderEntity
2.添加了 TickListenerComponent 这个数据组件,监听者就是自己,当触发时修改 txt 的显示
运行游戏,可以看见UI已经发生了变化!
ok这样简单的逻辑显示分离demo就完成了
基本思想是这样,后续会优化一下我们的代码结构,添加一个回滚功能!