Unity使用ECS架构entitas实现ui响应及回放系统

前言

最开始听说了守望先锋在开发的时候,使用了一个ECS的框架,就非常感兴趣。
ECS是一个可以基于现有的游戏引擎开发的架构,它是Entity、Component、System的集合简称,在游戏开发中,component仅用来存储数据,多个component可组成一个entity,而system多用于操作component,真正做到了以数据驱动游戏。
说到数据驱动的好处,就不得不提守望先锋的回放系统,在游戏中可谓是相当惊艳的功能,说得通俗一点,只要存储了数据,就能在你想看的时候,再重现一遍。

Entitas

在了解一些ECS架构的特点就希望自己能使用实际操作一下,然后在网上找到了entitas架构,然后还发现实际上早在unite2015和2016上,都有过相关的演示演讲,只能说自己孤陋寡闻了。
在github的介绍,Entitas是针对c#和unity实现ECS快速架构的解决方案。这就很完美的了,不需要重复造轮子,自然省下不少时间。

Entitas is a super fast Entity Component System (ECS) Framework specifically made for C# and Unity

github链接:https://github.com/sschmid/Entitas-CSharp

性能对比

演讲中还提到了与unity的MonoBehaviour的性能对比
这里写图片描述

HelloWorld

  • 下载entitas,并导入到unity工程中
  • 在unity中,选择Tools/Entitas/Preferences,全部设置为Everything,因为是简单demo,Contexts也只设置为Game,在前面的版本Contexts其实叫pool,所以也可以理解为对象池,所有的Entity都是从这里取的
    这里写图片描述
  • 按下Shift+ctrl+G,开始编译
  • 新建一个脚本GameController,并开始实现简单的System添加
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Entitas;

public class GameController : MonoBehaviour {

    Systems _systems;

    // Use this for initialization
    void Start () {
        var contexts = Contexts.sharedInstance;

        _systems = CreateSystems(contexts);

        _systems.Initialize();
    }

    // Update is called once per frame
    void Update () {
        _systems.Execute();
        _systems.Cleanup();
    }

    private void OnDestroy()
    {
        _systems.TearDown();
    }

     Systems CreateSystems(Contexts contexts)
    {
        return new Feature("Root System")
            ;
    }
}
  • GameController绑定在场景的物体的中,运行就能看见场景的System与GameContext

回放系统

  • 准备
    • 在看了entitas在unite2016演示后,然后就打算重现一下他演示的demo。
    • 首先说一下思路,demo以计数帧来驱动游戏的,然后记录下在某一帧的重要操作,然后在实现回放系统的时候,只需要从0开始重新运算,并在记录帧更新响应的数据,就实现了回放的系统,就这么简单,一方面这只是一个demo,一方面记录数据量不大,在实际中肯定还需要做一些优化计算的,不过还是大致思路还是一样的。
    • 这里有一个技巧就是,为了方便我们操作回放系统的数据,我们可以将回放系统的相关Systems,作为一个变量存在Component中。
  • 实现一个简单的ui界面
  • 为我们所需要的数据定义Component,这时候我们只需要新建一个类继承至IComponent即可,然后为其添加相应的变量,比如当前帧,能量值,消耗能量,是否为暂停。其中标记Game表示你所对应的Contexts,Unique表示唯一Entity
using Entitas;
using Entitas.CodeGeneration.Attributes;

[Game,Unique]
public class TickComponent:IComponent
{
    //当前帧
    public long currentTick;
}
using Entitas;
using Entitas.CodeGeneration.Attributes;

[Game,Unique]
public class ElixirComponent:IComponent
{
    //能量值
    public float amount;
}
using Entitas;

[Game]
public class ConsumeElixirComponent:IComponent
{
    //消耗的能量值
    public int amount;
}
using Entitas;
using Entitas.CodeGeneration.Attributes;

[Game,Unique]
public class PauseComponent:IComponent 
{

}
  • 在unity中按下Shift+Ctrl+G开始编译
  • 然后编写自己的TickUpdateSystem,IInitializeSystem是初始化执行的接口,IExecuteSystem是Unity的Update或者FixedUpdate执行的接口
using Entitas;
//更新帧计数
public class TickUpdateSystem : IInitializeSystem, IExecuteSystem
{
    readonly GameContext _context;
    public TickUpdateSystem(Contexts contexts)
    {
        _context = contexts.game;
    }

    public void Initialize()
    {
        _context.ReplaceTick(0);
    }

    public void Execute()
    {
        if (!_context.isPause)
            _context.ReplaceTick(_context.tick.currentTick + 1);
    }
}
  • 然后将TickUpdateSystem,添加到最开始的Root System,在GameContext下就可以看着帧数的变化
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Entitas;

public class GameController : MonoBehaviour {

    Systems _systems;

    // Use this for initialization
    void Start () {
        var contexts = Contexts.sharedInstance;

        _systems = CreateSystems(contexts);

        _systems.Initialize();
    }

    // Update is called once per frame
    void Update () {
        _systems.Execute();
        _systems.Cleanup();
    }

    private void OnDestroy()
    {
        _systems.TearDown();
    }

     Systems CreateSystems(Contexts contexts)
    {
        return new Feature("Root System")
        .Add(new TickUpdateSystem(contexts))
            ;
    }
}

演示

这里写图片描述

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
UnityECS架构是一种基于数据的设计模式,它将游戏对象(GameObject)拆分为各个组件(Component),并且通过系统(System)来处理这些组件,以此来实现游戏逻辑的编写和管理。 在ECS架构中,数据和逻辑是分离的,每个组件只包含数据,而不包含任何逻辑。而系统则负责处理这些组件,并且根据组件的数据状态来执行相应的逻辑。 下面详细介绍UnityECS架构: 1. 实体(Entity) 在ECS架构中,实体(Entity)是游戏对象(GameObject)的抽象。它只是一个ID,用于标识一个游戏对象。实体没有任何的组件或者逻辑。 2. 组件(Component) 组件(Component)是游戏对象的基本元素。每个组件只包含数据,不包含任何逻辑。例如,Transform组件只包含位置、旋转和缩放等数据,而不包含任何移动或旋转的逻辑。 3. 系统(System) 系统(System)是处理组件的核心。系统会根据组件的数据状态来执行相应的逻辑。例如,移动系统会根据Transform组件的位置和速度等数据来更新游戏对象的位置。 系统可以根据需要访问一组或多组组件,并且可以通过查询语言(Query)来获取需要的组件。例如,一个移动系统可能需要访问Transform组件和Velocity组件,它可以使用查询语言来获取这些组件。 4. 状态组件(State Component) 状态组件(State Component)是一种特殊的组件,它包含游戏对象的状态信息,例如是否存活、是否受伤等。系统可以根据状态组件的数据状态来执行相应的逻辑。例如,死亡系统会根据是否存活状态组件来判断游戏对象是否死亡。 5. 事件(Event) 事件(Event)是一种可以触发系统执行逻辑的机制。例如,当游戏对象被攻击时,可以触发一个受伤事件,从而让受伤系统进行处理。 6. 工作流(Workflow) 工作流(Workflow)是一种将多个系统组合起来处理游戏逻辑的机制。例如,一个游戏对象可能需要先执行移动系统,然后再执行攻击系统,最后再执行死亡系统。工作流可以让这些系统按照一定的顺序来执行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神码编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值