Unity——十分钟上手Unity ECS教程

前言
随着Unity新版本迭代,ECS也逐渐走入大家的视野,甚至有人在Unity官方论坛发问ECS是否已经成熟稳定可以商用。本人也是在学习当中,网上已经有各种深入浅出的说明,但缺乏一个可以跟着敲代码的demo、让人短时间内就能从代码层面了解ECS的教程。
本文就致力于用最简单的方式,让你跟着敲一遍代码就大概知道什么是ECS。
Demo内容
场景里放个球,键盘上下左右控制位移。
实战
1. 新建一个工程,确认你的版本支持ECS,我这里用的是2018.3

修改PlayerSetting->Other Setting->Configuration->Scripting Runtime Version为4.x
接下来在工程的Package目录(Assets同级)放入manifest文件以启用ECS框架
点此获取官方manifest样例
2. 在ECS框架中,原本类似MonoBehavior的职能被拆分成纯数据以及操作数据的系统,所以你将会看到大量xxxComponent,xxxSystem的类。比如接下来我们就要建立一个只带移动方向的移动组件、修改移动方向的输入系统以及控制移动的移动系统。
3. 新建几个C#文件:
表示移动数据的MoveComponent.cs

    using Unity.Entities;
    using UnityEngine;

    public class MoveComponent : MonoBehaviour
    {
        public Vector3 moveDir;
    }

 

表示移动系统的MoveSystem.cs

using Unity.Entities;
using UnityEngine;

public class MoveSystem : ComponentSystem
{
    public struct Filter
    {
        public Transform tf;  
        public MoveComponent moveComponent;
    }

    protected override void OnUpdate()
    {
        foreach (var entity in GetEntities<Filter>())
        {
            Vector3 pos = entity.tf.position + entity.moveComponent.moveDir * Time.deltaTime * 3;
            entity.tf.position = pos;
        }
    }
}

 

表示输入系统的InputSystem.cs

    using Unity.Entities;
    using UnityEngine;

    public class InputSystem : ComponentSystem
    {
        struct Data
        {
            public ComponentArray<MoveComponent> moveArray;
        }

        [Inject] private Data _data;
        protected override void OnUpdate()
        {
            for (int i = 0; i < _data.moveArray.Length; ++i)
            {
                _data.moveArray[i].moveDir = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);
            }
        }
    }



4. 场景中新建一个球体,添加一个GameObjectEntity组件以及我们刚刚新建的MoveComponent组件
5. 启动游戏,按一下上下左右,是不是可以控制球的移动了?
原理
在上面的例子里,输入系统每帧检测输入,把输入赋给移动组件,_data是包含所有MoveComponent的数组,这个数组是通过[Inject]属性标签注入进去的。这个注入的标签很有意思,它会匹配好里面你需要的组件给你放进去,它的原理我们找时间再深入研究。而移动系统就更简单了,就是遍历所有移动组件,然后根据moveDir去移动它对应的transform。
大概你也注意到了InputSystem和MoveSystem的遍历方式是不一样的,这是为了演示可以有不同的遍历方式。而且要注意,上面例子里MoveComponent继承自MonoBehavior,如果它继承自IComponentData,它就只能是一个struct,而struct并不能够像MoveSystem那样去遍历,而且也不能直接用组件方式添加到一个GameObject上了。
继承自IComponentData的好处自然是让纯数据的组件以及系统与GameObject分离,试想一下你可以同时跑100w个移动的对象,但这些对象却不一定需要一个GameObject,这就是ECS带来性能提升的一大原因。
你可能觉得奇怪,球上只添加了两个组件,怎么就移动了,MoveSystem既没new出来也没拖到什么对象上,谁在激活这些系统?答案是世界,当然这是另一个话题了,在本篇里你只需要知道有个“世界”在运行你写的System就够了,只要你写了个系统继承自ComponentSystem,它就会被执行。

发布了97 篇原创文章 · 获赞 21 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/sun124608666/article/details/100692871