# ECS-Learn **Repository Path**: ezark/ECS-Learn ## Basic Information - **Project Name**: ECS-Learn - **Description**: ECS框架学习 - **Primary Language**: C# - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2020-04-08 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ECS +JobSystem ECS在各种Unity版本上表现都不一样,官方给的例子如果用Unity2018.3.1打开就会满处飘红。坑很多,文档像屎一样看了很多博客,终于找到一个能用的,完成了一个小demo,十万个小立方体围着中间转,有三种不同的材质,最后跑了70帧,大功告成,可喜可贺。 一开始有点困惑,不过好在之前接触过StrangeIOC框架,用抽象的概念去理解,很快就明白了。(大部分时间都坑在ECS迷幻的版本更新上了) ECS 就是Entity Component System的缩写 + Entity 实体,只存储数据。自己写的时候继承自IComponentData, 但是这里面和StrangeIOC的数据接口不一样,要求数据不能是Class,而必须是Struct.看了别人的博客,说用struct存储会直接写入到数据栈中,是一连串紧密的数据结构,节约cpu开销,增加速度 + Component 这里的Component和之前有很大区别,之前Component就是在物体上挂n个monobehavior,ECS框架里面的组件把Position,Rotation,Scale……能拆的全拆开了,用到哪个再把哪个挂上,再也不用担心一个游戏物体挂一万个Monobehavior + System 转门处理所有的运算逻辑,最好配合JobSystem开多线程,卡顿什么的再也不存在了。 # Entity例子 ```csharp [Serializable] public struct MovementData : IComponentData {//不允许有逻辑和对外依赖 public float theta; public float3 center;//轴心 public float omega;//角速度 public float radius;//半径 public float p; } ``` 除了之前提到的地方,Entity还有一处和以往不一样,不用vector3而是使用float3,float3也是简化版的vector3,基本无缝对接到vector3,用起就对了。 # Component例子 ```csharp public class MovementComponent : ComponentDataWrapper { } ``` 定义的Component包裹着这一组数据,这个在2018.3.1当中变成了ComponentDataProxy,这个组件相当于简易版的Monobehaivor,需要手动或者用代码挂到物体上 # System例子 ```csharp public class MovementSystem : JobComponentSystem { [BurstCompile] struct MovementJob : IJobProcessComponentData { /// /// 中心点及半径数据 /// public quaternion targetRotation; public float deltaTime; public void Execute(ref Position position, ref Rotation rotation,ref MovementData data) { float theta = data.theta+ data.omega* deltaTime; float x = data.center.x + data.radius* Mathf.Cos(theta)*Mathf.Sin(data.p); float y = data.center.y+ data.radius *Mathf.Cos(data.p); float z = data.center.z + data.radius * Mathf.Sin(theta) * Mathf.Sin(data.p); position = new Position { Value = new float3(x, y, z) }; rotation = new Rotation { Value = targetRotation }; data = new MovementData { theta=theta, center = data.center, radius = data.radius, omega = data.omega, p=data.p }; } } protected override JobHandle OnUpdate(JobHandle inputDeps) { MovementJob moveJob = new MovementJob { deltaTime = Time.deltaTime, targetRotation = Quaternion.LookRotation(Camera.main.transform.up) }; moveJob.deltaTime = Time.deltaTime; JobHandle jobHandle = moveJob.Schedule(this, inputDeps); return jobHandle; } } ``` 在这里会遍历所有Entity,挨个执行程序。因为会开多线程所以速度会非常快 最后挂一个Monobehaviour挂脚本,执行安装程序(其实这部分也可以不挂脚本用静态类来实现,Prefab,Metarial从Resources.Load当中读取等等,理论上可以实现一行脚本都不挂的跑程序。) ```csharp public class GameManager : MonoBehaviour { public EntityManager entityManager; public EntityArchetype entityArchetype; public int createPrefabCout; public GameObject prefab; Mesh mesh; public Material[] materials; public Transform centerTrans; // Use this for initialization void Start () { mesh = prefab.GetComponent().sharedMesh; entityManager = World.Active.GetOrCreateManager(); NativeArray entities = new NativeArray(createPrefabCout, Allocator.Temp); entityManager.Instantiate(prefab, entities); for (int i = 0; i < createPrefabCout; i++) { //设置组件 entityManager.SetComponentData(entities[i], new Position { Value = UnityEngine.Random.insideUnitSphere * 100 }); entityManager.SetComponentData(entities[i], new Rotation { Value = quaternion.identity }); float randRadius = UnityEngine.Random.Range(2, 1000); float randOmega = UnityEngine.Random.Range(-10, 10); float randTheta = UnityEngine.Random.Range(0, 360); float randp= UnityEngine.Random.Range(0, 360); entityManager.SetComponentData(entities[i], new MovementData { center = centerTrans.position, omega = randOmega, radius = randRadius, theta = randTheta, p=randp }); int colorIndex = UnityEngine.Random.Range(0, 3); Debug.Log(colorIndex); //添加并设置组件 entityManager.AddSharedComponentData(entities[i], new MeshInstanceRenderer { mesh = this.mesh, material = this.materials[colorIndex], }); } entities.Dispose(); } } ``` # 最终结果: ![result](result.png) 帧率:75左右,相当不错 生成的片有10w个。 源码地址:[ECS框架学习的源码地址](https://gitee.com/sika0819/ECS-Learn.git)