小言_互联网的博客

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

309人阅读  评论(0)

继续上一章说:传送门

目的:
添加完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就完成了
基本思想是这样,后续会优化一下我们的代码结构,添加一个回滚功能!


转载:https://blog.csdn.net/qq_33064771/article/details/117093491
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场