2026/2/14 12:33:55
网站建设
项目流程
怎样将建设银行网站加入可信站,wordpress注册跳转,页面设计结课总结,东莞市房管局官方网站观前须知
ECS是一种用于处理大量运算#xff0c;性能极高的架构#xff0c;在某些特定的情况下可能发挥很大作用#xff0c;由于所蕴含的知识很多#xff0c;而我只粗学了10多个小时#xff0c;某些地方可能会有纰漏#xff0c;看不懂或者讲错了直接喷
注:需要导入的一些…观前须知ECS是一种用于处理大量运算性能极高的架构在某些特定的情况下可能发挥很大作用由于所蕴含的知识很多而我只粗学了10多个小时某些地方可能会有纰漏看不懂或者讲错了直接喷注:需要导入的一些包这里就不再赘述了加载SubScene什么的这里也不再提及正式开始ECS即Entity(实体),“Component(组件)”,System(系统)简单来说就是组件挂载在实体上执行系统中的规则与传统unity的区别是原本unity执行的规则放在组件上,下面我们分开来讲这三个部分组件Component这里的Component实际上充当了Data的作用主要是用来存放一些字段数据下面给出一个简单的例子public struct RotateSpeed : IComponentData { public float Speed; }注意这里使用结构体是为了让Data为非托管类型如果你非要用class也不是不可以只是会让性能下降很多还有一点请不要在结构体中放托管类型的字段否则也会让它性能下降实体Entity实体只负责承载Component本身没有任何字段和方法想要给实体上放置组件我们不能直接把ComponentData拖到对象上面我们可以用Baker的方法public class RotateSpeedAuthoring : MonoBehaviour { [SerializeField] private float _speed; [SerializeField] private bool _startRotate; public float Speed _speed; public bool StartRotate _startRotate; private class Baker : BakerRotateSpeedAuthoring { public override void Bake(RotateSpeedAuthoring authoring) { Entity entity GetEntity(TransformUsageFlags.Dynamic);//也可以用None,Dynamic是可动的None一般是不需要它的位置的 AddComponent(entity, new RotateSpeed() { Speed authoring.Speed, }); //先忽略 SetComponentEnabledRotateSpeed(entity,authoring.StartRotate); } } }这里的Baker是Mono脚本的一个子类可以在游戏开始是给挂载该脚本的对象实体添加一个Component。注意这里的GetEntity方法参数可以为动态或静态它会让世界给你返回一个实体的引用你可以为它添加自己想要的组件并为对象设置想要的初始值。除了用Baker在开始时添加组件还有另外三种常用的方法添加组件,它们分别是在主线程动态增删的EntityManager和EntityCommandBuffer还有在多线程中增删的EntityCommandBuffer.ParallelWriter至于它们我们会在下一段见到系统System系统是最核心的一部分包含了整个世界的规则简单举一个例子就是让所有长翅膀的动物会飞这就是一个简单的系统了系统要做的事其实就这么几步查找所有动物看谁长了翅膀然后让它飞起来。最多需要在开始时先查找一遍有没有长翅膀的动物如果没有就不查找了节省性能。至于这里的查找主要有三种常用方法Query,Job和Chunk.我们来以一个简单的系统来依次看看Query[BurstCompile] partial struct RotateCubeSystem : ISystem { private float _timer; private const float INTERVAL 1f; [BurstCompile] public void OnCreate(ref SystemState state) { state.Enabled false;//这里如果用false系统就不运行了记得删!!! state.RequireForUpdateRotateSpeed();//找寻世界里有没有对应组件没有就不Update } [BurstCompile] public void OnUpdate(ref SystemState state) { foreach (var (transform, speed) in SystemAPI.QueryRefRWLocalTransform, RefRORotateSpeed()) { transform.ValueRW transform.ValueRO.RotateY( speed.ValueRO.Speed * DeltaTime); } } [BurstCompile] public void OnDestroy(ref SystemState state) { } }这里就是最简单的一个Query下面我们依次解析可能会看不懂的地方首当其冲的是 [BurstCompile],这个标签是为了提升性能但是如果方法中有托管对象就会报错比如GameObject第二查询Query,前面的类是var加一个元组元组是用来简化代码的关键看后面.QueryRefRW, RefRO()查询世界中所有带LocalTransform和RotateSpeed的实体并返回LocalTransform的读写RotateSpeed的可读引用用LocalTransform主要是因为unity内置的Transform用不了只能用它改变它的旋转后面就是简单的改变transform的值了没有好讲的了这里的Query性能不高但是理解起来容易我们来给他改成job,性能更高理解起来稍稍有些困难Jobjob类 [BurstCompile] public partial struct RotateCubeJob : IJobEntity { public float DeltaTime; void Execute(ref LocalTransform transform, ref PostTransformMatrix postTransform, in RotateSpeed speed) { transform transform.RotateY(speed.Speed * DeltaTime); } } //使用把上面一段foreach改成 RotateCubeJob job new RotateCubeJob() { DeltaTime SystemAPI.Time.DeltaTime }; state.Dependency job.ScheduleParallel(state.Dependency);这里为什么要传一个DeltaTime作为参数因为job中不能使用SystemAPI.Time.DeltaTime所以需要外界给他传进去Execute方法其实和上面的Query差不多只不过把可写参数加上ref,可读参数加上in其他几乎就是照搬最后的使用只要先new一个job然后job.Schedule()就好了最后的chunk性能最高当然代码也有点繁琐注意不是困难是繁琐Chunkchunk类注意Execute参数固定 public struct RotateCubeJobChunk : IJobChunk { public ComponentTypeHandleLocalTransform TransformTypeHandle; [ReadOnly] public ComponentTypeHandleRotateSpeed RotateSpeedTypeHandle; public float DeltaTime; [BurstCompile] public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask) { var transforms chunk.GetNativeArray(ref TransformTypeHandle); var speeds chunk.GetNativeArray(ref RotateSpeedTypeHandle); for(int i0; ichunk.Count;i) { transforms[i] transforms[i].RotateY(speeds[i].Speed * DeltaTime); } } } chunk的使用 var spinningCubesQuery SystemAPI.QueryBuilder().WithAllRotateSpeed, LocalTransform().Build(); RotateCubeJobChunk chunk new RotateCubeJobChunk() { DeltaTime SystemAPI.Time.DeltaTime, TransformTypeHandle SystemAPI.GetComponentTypeHandleLocalTransform(), RotateSpeedTypeHandleSystemAPI.GetComponentTypeHandleRotateSpeed(true), }; //state.Dependency chunk.Schedule(spinningCubesQuery,state.Dependency);chunk里面所有用到的Component都要用到句柄的方式。其中只读的要加上只读标签然后在使用是从句柄中取到引用spinningCubesQuery是取到所有有对应组件实体的队列chunk的Schedule方法要用到这个队列后面几乎就差不多了把句柄通过SystemAPI的获得句柄的方式传进去句柄最好在开始时缓存起来附加内容碍于篇幅限制下面用几句简单的话解释知识点在系统上加上[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]这个标签它的Update函数会变成类似unity的FixedUpdate系统除了可以继承自ISystem,还可以继承自SystemBase在它的里面放托管类型字段方法作为ECS世界和Mono世界的桥梁想要大量生成预制体用Component存Entity,再在烘焙时把Component里面的EntityGetEntity(prefab,TransformUsageFlags.Dynamic),再state.EntityManager.Instantiate(prefab, 200, Allocator.Temp);就好记得如果数量过多就要把第三个参数的Temp改成永久并在完成后Dispose可以通过SystemAPI.GetSingleton获取某个组件单例大概基础只能写这么多能看懂谢天谢地希望能出第二期…………或者学HybridCLRAddressable也好啊