欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity使用Entitas开发逻辑显示分离Demo(二)

程序员文章站 2022-03-17 10:37:50
...

继续上一章说:传送门

目的:
添加完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,然后给他挂一个脚本
Unity使用Entitas开发逻辑显示分离Demo(二)

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已经发生了变化!
Unity使用Entitas开发逻辑显示分离Demo(二)

ok这样简单的逻辑显示分离demo就完成了
基本思想是这样,后续会优化一下我们的代码结构,添加一个回滚功能!