找回密码
 立即注册
查看: 432|回复: 0

[简易教程] 十分钟上手Unity ECS

[复制链接]
发表于 2020-12-31 12:44 | 显示全部楼层 |阅读模式
前言

随着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
  1. using Unity.Entities;
  2. using UnityEngine;
  3. public class MoveComponent : MonoBehaviour
  4. {
  5.     public Vector3 moveDir;
  6. }
复制代码
表示移动系统的MoveSystem.cs
  1. using Unity.Entities;
  2. using UnityEngine;
  3. public class MoveSystem : ComponentSystem
  4. {
  5.     public struct Filter
  6.     {
  7.         public Transform tf;  
  8.         public MoveComponent moveComponent;
  9.     }
  10.     protected override void OnUpdate()
  11.     {
  12.         foreach (var entity in GetEntities<Filter>())
  13.         {
  14.             Vector3 pos = entity.tf.position + entity.moveComponent.moveDir * Time.deltaTime * 3;
  15.             entity.tf.position = pos;
  16.         }
  17.     }
  18. }
复制代码
表示输入系统的InputSystem.cs
  1. using Unity.Entities;
  2. using UnityEngine;
  3. public class InputSystem : ComponentSystem
  4. {
  5.     struct Data
  6.     {
  7.         public ComponentArray<MoveComponent> moveArray;
  8.     }
  9.     [Inject] private Data _data;
  10.     protected override void OnUpdate()
  11.     {
  12.         for (int i = 0; i < _data.moveArray.Length; ++i)
  13.         {
  14.             _data.moveArray[i].moveDir = new Vector3(Input.GetAxis("Horizontal"), <span class="n">Input.GetAxis("Vertical"), 0);
  15.         }
  16.     }
  17. }
复制代码
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,它就会被执行。


好了,本文到这里就结束了,有时间的话还会继续深入整理ECS教程出来。本人水平有限,如有错漏请尽管指出。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-6-1 10:49 , Processed in 0.108229 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表