【Unity】Entities 1.0 学习(一):Aspect

这篇具有很好参考价值的文章主要介绍了【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 是自定义的的 BufferElementData
    private 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:

【Unity】Entities 1.0 学习(一):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;//声明一个Handle

        protected 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 ,还是非常困难的。文章来源地址https://www.toymoban.com/news/detail-404033.html

到了这里,关于【Unity】Entities 1.0 学习(一):Aspect的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Bootstrap学习笔记(1.0)

    Bootstrap是一个用于快速开发Web应用程序和网站的前端框架。Bootstrap是基于HTML、CSS、JavaScript的。 优点 它为开发人员创建接口提供了一个简洁统一的解决方案。 它包含了功能强大的内置组件,易于定值。 它还提供了基于Web的定制。 它是开源的。 Bootstrap包的内容 基本结构:

    2023年04月12日
    浏览(28)
  • Typescript学习笔记(1.0)

    typescript是由微软开发的自由和开源的编程语言。 typescript是JavaScript的一个超集,就是说JavaScript的语法typescript全部支持,并且在JavaScript进行了扩充,并在JavaScript的基础上进行了变量、函数、返回值等类型限制。 首先,是安装typescript。因为他需要编译,需要首先安装Node.js。

    2023年04月09日
    浏览(30)
  • 微信小程序开发(学习记录1.0)

    首先,把遇到的问题贴出来,主要是这个解决问题的思路,供大家参考。 现在的问题是将下面的导航栏做出来,但是在自己做的时候 遇到的问题 在app.json文件中输入tarBar,就会生成模板代码,默认会生成一个list的模板代码,几个list就是下面的导航栏有几部分,我们想要分成

    2024年02月09日
    浏览(25)
  • 【深度学习】BERT变种—百度ERNIE 1.0

          ERNIE: Enhanced Representation through Knowledge Integration是百度在2019年4月的时候,基于BERT模型,做的进一步优化,在中文的NLP任务上得到了state-of-the-art的结果。         ERNIE 是百度开创性提出的基于知识增强的持续学习语义理解框架,该框架将大数据预训练与多源丰富知

    2024年02月08日
    浏览(35)
  • H-buildX项目(学习笔记1.0)

    记录一下自己的学习过程。 首先,下载H-buildX软件,直接度娘下载即可。 以前一直用的是vscode,这次做网上的项目用到了这个。 打开 就是这样的界面,首先介绍几个常用的功能 右上角的预览,也就是运行你的Vue项目的界面效果,下面就是展示界面   当前了,如果代码不能

    2024年02月06日
    浏览(24)
  • this.viewer.entities.removeById()循环删除为什么删除不完

    在 Cesium 中, viewer.entities.removeById() 方法用于从场景中移除指定 ID 的实体。如果您在循环中使用这个方法来删除多个实体,有可能会出现删除不完全的问题,这是因为在删除实体的同时,实体数组的长度在不断减小,可能会导致索引错位或者遗漏某些实体。 要安全地从实体集

    2024年02月11日
    浏览(28)
  • 论文笔记--ERNIE: Enhanced Language Representation with Informative Entities

    标题:ERNIE: Enhanced Language Representation with Informative Entities 作者:Zhengyan Zhang, Xu Han, Zhiyuan Liu, Xin Jiang, Maosong Sun, Qun Liu 日期:2019 期刊:ACL   文章提出了ERNIE(Enhanced Language Representation with Informative Entities),一种可以将外部知识融合进入预训练模型的方法。数值实验表明,ERNI

    2024年02月16日
    浏览(26)
  • Unity2023, Unity2022, Unity2021的性能对比(帧率)

    最近由于需要用到Unity最新版的一些功能,比如Spline,比如Foward+渲染,新项目用了Unity2022.3.5版本,但是出包之后,感觉帧率很低。本着好奇的态度,专门写了一个测试场景,分别在Unity2023.1.15,Unity2022.3.5,Unity2021.3.14版本,进行了测试,分别得出帧率: Unity 2023.1.15 -- 97 帧左

    2024年02月07日
    浏览(45)
  • TM4C123GH学习笔记(1.0)——keil搭建开发环境

    关于安装keil5 KDM的教程参考B站江科大即可。本文需要安装好keil5。 本文附有keil的pack和相关驱动,以及创建好的空工程: 百度云链接:提取码:tc1e 站内链接:CSDN下载(免费)      打开设备管理器     选择文件夹下的驱动    装好之后,插着TM4C123GH6PM板子可以检测到ICDI。

    2024年02月17日
    浏览(31)
  • SpringBoot简单使用切面类(@aspect注解)

    简介 Spring Boot中的AOP(Aspect Oriented Programming, 面向切面编程)可以让我们实现一些与业务逻辑无关的功能,如日志、事务、安全等。 特点 把这些跨切面关注点抽取出来,实现解耦。 使用切面承载这些功能的实现,而不污染业务逻辑。 在定义好的切入点Join Point,执行这些功能,比如方

    2024年02月10日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包