【Unity】Entities 1.0 学习(一):Aspect
Unity在 2022年下半年(我印象是9月份左右)推出了 Entities 1.0 ,可以在 2022.2.0b8 以上的版本使用。当时我粗略地看了一下,但是没有深入学习。最近空闲时间稍多,就认真来学习一下 Entities 1.0有啥新的东西。
1.0 毕竟是大更新,改变的东西还是很多,所以应该会断断续续分好几次更新。
首先来看官方的更新文档:
What's new in Entities 1.0 | Entities | 1.0.0-exp.12https://docs.unity3d.com/Packages/com.unity.entities@1.0/manual/whats-new.html 新增的功能有很多了,我就不一一列举了,需要的同学自行看文档了。我就一个一个的来看,学到哪里算哪里。
这篇文章是 Entities 1.0 的介绍,不是 ECS 相关的入门。我默认你已经熟练使用之前版本的 Unity ECS,只是对 1.0 的更新缺乏了解的。如果没有 ECS 的相关知识,不建议阅读此文,建议先学习 ECS 并有初步的理解。
我目前看的版本是 1.0.0-exp.12 ,后续Unity可能会做一些更改,但是应该不会很大。
1、什么是Aspect
简单地理解就是 ComponentData 的二次封装 。
Aspect 是 1.0 新增一个新特性,允许将多个CompoenentData 或是 Buffer 组合在一起,这样使用起来就更加方便,感觉更像面向对象了。
Organize your code with aspects | Entities | 1.0.0-exp.12https://docs.unity3d.com/Packages/com.unity.entities@1.0/manual/aspects-intro.html 例如我在某个Entity上挂载了多个 ComponentData 时,我可以通过 Aspect 将他们全部拿到并自定义一些方法,而不必要再像以前那样拿到各个单独的 ComponentData 然后分别修改。不但在设计上更为友好,同时还能大量减少重复代码。
关于重复代码:
在以前的书写中,如果某段逻辑在多个 System 中都会使用,要么是重复写代码,要么放到一个公共类。而放到公共类中,如果涉及到大量参数传递时也会很恶心。
而在 Aspect 中,我们可以将公共方法直接卸载 Aspect 中,其值获取可以直接由内部属性构造获取,非常方便。
2、构建 Aspect
接下来从一个实例开始介绍 Aspect :
public readonly partial struct BuildAspect : IAspect
{//下面的 UTransform 和 UBounds 都是自定义的 ComponentData private readonly RefRW<UTransform> mTransfrom;private readonly RefRO<UBounds> mBounds;//RenderPartParentBuffer_Child 是自定义的的 BufferElementDataprivate readonly DynamicBuffer<RenderPartParentBuffer_Child> mChilds;
}
readonly partial 是固定写法,这个不能改,然后继承 IAspect,并且添加至少一个 RefRO / RefRW 即可完成对 Aspect 的构建。
当然,在 Aspect 里也是可以嵌套其他 Aspect 的。
在代码编译阶段,Unity会根据你写的 Aspect 代码自动生成(派生类)对应的创建代码,以及Handler(下文会看到,在System内部使用的)之类,这种机械代码完全就可以不用写了。
关于:IAspectCreate<T>
如果你浏览 Unity.Transforms.TransformAspect 的时候,你会发现他继承了这个 IAspectCreate<T>。但实际上我们自己写的时候是不需要的,只需要继承 IAspect 即可。实际上当我们阅读 TransformAspect 发现非常复杂,实现绕来绕去的,是因为我们看到的代码包含了自动生成的代码。而我们自己写的时候是不需要写这些的。
当继承 IAspect 之后,编译时 Unity 会自动生成一个派生并继承 IAspectCreate<T>,并自动写完所需要的代码。如果我们自己继承了 IAspectCreate<T> ,还需要自己写生成代码。
当然,就上文的代码还看不出有什么用,但是我们将其功能完善之后你就能看出端倪了:
public readonly partial struct BuildAspect : IAspect{private readonly RefRW<UTransform> mTransfrom;private readonly DynamicBuffer<RenderPartParentBuffer_Child> mChilds;private readonly RefRO<UBounds> mBounds;public float3 Position{get { return mTransfrom.ValueRO.Position; }set { mTransfrom.ValueRW.Position = value; }}public quaternion Rotation{get { return mTransfrom.ValueRO.Rotation; }set { mTransfrom.ValueRW.Rotation = value; }}public UBounds Bounds => mBounds.ValueRO;public RenderPartParentBuffer_Child GetFirstChild => mChilds[0];}
显然,这里面就和我们平时写的C#就差不多了,几乎没有限制,可以自由地调用现有属性完成逻辑。我们大可以在这个基础上完成一些逻辑的封装,从而使ECS代码更接近大家熟知的面向对象模式。
3、主线程调用 Aspect
主线程只需要通过EntityManager来获得这个Aspect即可:
Entity e = Entity.Null;//示例;
EntityManager mananger = default;//示例;var buildAspect = mananger.GetAspect<BuildAspect>(e);
buildAspect.Position = 0;//设置位置 Test
很显然,看得出来Aspect所谓的获取,其实就是重新构建一个新的结构体,Unity并没有设计一个缓存之类的。
在主线程调用这个非常友好,直接都可以当做一个Class来使用都是没有问题的。
4、System中调用Aspect
相比较而言,在System中调用就麻烦很多了。
非常搞笑的是,Unity的官方文档里说在System里可以用SystemAPI来创建Aspect:
实际上这个API根本不能用,里面就没有实现,谁调用谁报错(笑)。
大家可以看看官方文档,是不是我的理解有问题。
4.1、在 IJobEntity 中使用 Aspect
在 IJobEntity 的写法则非常简单,啥预处理都不用,直接像下面这样写就可以:
using Unity.Entities;
using Unity.Burst;// It's best practice to Burst-compile your code
[BurstCompile]
partial struct CannonBallJob : IJobEntity
{void Execute(ref CannonBallAspect cannonBall){// Your game logic}
}
就这样就轻松愉快地可以用起来了。
4.2、在 IJobChunk 中使用 Aspect
而在 IJobChunk 中用起来麻烦多了,需要做的工作不是多一点点:
public partial class EcsTestBuildSystem : SystemBase
{private EntityQuery mEntityQuery;private BuildAspect.TypeHandle _aspectTypeHandle;//声明一个Handleprotected override void OnCreate(){base.OnCreate();mEntityQuery = GetEntityQuery(ComponentType.ReadWrite<UTransform>(),ComponentType.ReadWrite<RenderPartParentBuffer_Child>(),ComponentType.ReadOnly<UBounds>(), );_aspectTypeHandle = new BuildAspect.TypeHandle(ref CheckedStateRef, false);}protected override void OnUpdate(){ _aspectTypeHandle.Update(ref CheckedStateRef);//更新Dependency = new EcsTestRunner_Update(){BuildAspectHandle = _aspectTypeHandle//传值}.ScheduleParallel(mEntityQuery, Dependency);}[BurstCompile]private struct EcsTestRunner_Update : IJobChunk{public BuildAspect.TypeHandle BuildAspectHandle;public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask){var builds = BuildAspectHandle.Resolve(chunk);for (int i = 0; i < chunk.Count; i++){var build = builds[i];}}}}
瞬间代码量就上去了!
在 IJobChunk 中使用Aspect之所以麻烦,是因为这里几乎所有的代码都是要我们自己写的。而在 IJobEntity 中,大部分代码都是 Unity 在派生类中帮助我们写好了。
但是我还是建议使用 IJobChunk , 麻烦但是有意义的。你可以理解为这个是 Job 的一种高级写法,我们可以通过这个控制 Chunk,虽然麻烦了点,但是可以获取更高的效率。如果要真的用好 ECS ,IJobChunk 肯定是家常便饭。
5、其他注意事项
构建 Aspect 是会有额外消耗的,毕竟每次都会创建一个新的。所以如果追求极致性能就不要使用这个。
在 Aspect 的写入其实是单线程的,如果是多线程写入会提示线程竞争。所以要么单线程跑,要么加上 NativeDisableParallelForRestriction 属性。
Aspect 在以读写的方式构造时,无论改了哪些属性,都会将里面的所有值设置为修改,自然也会损失一些性能。构建一个 Aspect 很容易,但是要构建一个高效率的 Aspect ,还是非常困难的。
【Unity】Entities 1.0 学习(一):Aspect相关推荐
- 【Unity】Entities 1.0 学习(二):调试工具
在 Entites 1.0 ,Unity修改了之前的调试面板,以及在场景下构建 Ecs World 的流程,较之前的版本差别还是蛮大的. 之前的学习大多集中在代码和语法,很多是对之前成熟的代码做升级改 ...
- (转)[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(1)...
原文地址:http://www.cnblogs.com/kyo-yo/archive/2010/11/01/Learning-EntLib-Tenth-Decoupling-Your-System-U ...
- [EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART5——使用Unity自身的拦截器...
在前一篇文章中,介绍了如何使用Unity来接管PIAB进行拦截操作,而Unity自身也提供了类似于ICallHandler的拦截处理程序--IInterceptionBehavior,今天这篇文章就是 ...
- 小白如何从0学习unity
小白如何从0学习unity 博主是一名从本科某帝都知名财经院校转职到某帝都知名理工大学软件学院的研究生.由于本科专业课程偏向金融,导致自身对于自己的职业前景并没有一个很好的规划.在几经波折后,博主最后 ...
- Unity DOTS Entities1.0.0-pre.15文档翻译(随缘更新中...)
官方文档Entities overview | Entities | 1.0.0-pre.15 (unity3d.com) 一.Entities 总览 Entities包,是Unity"面向 ...
- Unity优化手机游戏学习教程
流派:电子学习| MP4 |视频:h264,1280×720 |音频:AAC,48.0 KHz 语言:英语+中英文字幕(根据原英文字幕机译更准确)|大小解压后:3.69 GB |时长:6h 44m 创 ...
- [EntLib]微软企业库5.0 学习之路——第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——上篇...
本文是为后面的学习之路做铺垫,简单介绍下企业库中的Validation模块的一些相关知识,包括Validation模块的简介.用途.使用方法.默认提供的多种验证器的介绍等. 一.简介及用途 在实际的项 ...
- [EntLib]微软企业库5.0 学习之路——第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—上篇...
在完成了后,今天开始介绍企业库中的新模块:Cryptographer(加密模块),这个模块在日常的大多数项目的作用非常重要,例如:网站会员密码.身份证号.网站配置等,通过对信息进行加密可以保证项目数据 ...
- Unity插件之NGUI学习(8)—— Table和NGUI尺寸转换为世界坐标系尺寸
依据 Unity插件之NGUI学习(2),创建一个UI Root,在UI Root下创建一个Texture作为背景图,并设置图片,在Wiget下调整大小:然后在UI Root下再创建一个Panel. ...
最新文章
- [转]gitHub客户端Desktop的安装使用总结 ---基础篇
- 求你了,别再用 pip 那乌龟的速度去安装库了!
- caffeImagenet相关
- jQuery如何选择表格每行中的第三列?
- 快速傅里叶变换(FFT)——按时间抽取DIT的基
- 只用一个循环实现层序遍历
- 在windows7桌面上新建一个快捷方式,指向cmd命令窗口
- 使用vue脚手架进行模块化开发
- 修改mysql字段长度
- 一个简单实用的boost升压电路
- 批量翻译软件免费【2022最新版】
- (十六)soul源码的自定义插件
- 处理团队中的消极情绪
- 仅1cm厚!华硕发布全球最薄13.3英寸笔记本
- 9.22生日——随笔
- 二叉树遍历(非递归)
- java归并排序详解
- 打包软件一键安装_InstallShield2015PremierComp打包软件安装步骤
- 解析json格式请求返回500状态码的异常
- 双目三维测距(python)
热门文章
- 单片机的字节寻址c语言,单片机C语言通用万能编程模板
- openstack-ceilometer第二式:源码分析-polling
- 驾考 php mysql,驾考理论模拟考试系统的设计与实现(PHP,MySQL)(含录像)
- 【python】灰色预测平均房价趋势kera深度学习库的介绍
- 在 Flutter 中使用 webview_flutter 4.0 | 基础用法与事件处理
- proftpd java_在CentOS 7.5上安装和配置ProFTPD
- 近4000个图标集,超过20万免费图标下载汇总贴
- 工业物联网·智慧油田远程监控系统方案
- Ruby读写excel表格
- vue3控制台一直报错, [WDS] Disconnected!