您当前的位置: 首页 > 

CloudHu1989

暂无认证

  • 4浏览

    0关注

    89博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

ECS官方案例3. IJobChunk

CloudHu1989 发布时间:2019-08-10 13:53:35 ,浏览量:4

基于Unity2019最新ECS架构开发MMO游戏笔记2
  • 官方案例解析3
    • 3. IJobChunk
    • 小结
      • DOTS 逻辑图表
  • 更新计划
    • 作者的话
  • ECS系列目录
    • ECS官方示例1:ForEach
    • ECS官方案例2:IJobForEach
    • ECS官方案例3:IJobChunk
    • ECS官方案例4:SubScene
    • ECS官方案例5:SpawnFromMonoBehaviour
    • ECS官方案例6:SpawnFromEntity
    • ECS官方案例7:SpawnAndRemove
    • ECS进阶:FixedTimestepWorkaround
    • ECS进阶:Boids
    • ECS进阶:场景切换器
    • ECS进阶:MegaCity0
    • ECS进阶:MegaCity1
    • UnityMMO资源整合&服务器部署
    • UnityMMO选人流程
    • UnityMMO主世界

官方案例解析3

开始之前的准备工作: 0下载Unity编辑器(2019.1.0f1 or 更新的版本),if(已经下载了)continue; 1下载官方案例,打开Git Shell输入: git clone https://github.com/Unity-Technologies/EntityComponentSystemSamples.git --recurse or 点击Unity官方ECS示例下载代码 if(已经下载了)continue; 2用Unity Hub打开官方的项目:ECSSamples 3在Assets目录下找到HelloCube/3. IJobChunk ,并打开IJobChunk 场景

3. IJobChunk

这个案例演示了基于Jobs的ECS系统如何旋转一对方块儿,与同样使用Jobs系统的案例2不同的是,在循环遍历的时候,前者迭代的是实体,而这个案例迭代的是块(内存块,这个块是被一开始基于相同原型分配好了的,也就是说,如果这20个实体有相同的组件,那么他们会被紧密的安排在一块内存中,从而方便处理器进行操作。这是相对于面向对象的散列内存而言的,在面向对象中要操作内存中的某个对象时,你不得不在整个内存中寻找它,这样会降低读取速度,也不方便批量操作。ECS则会非常紧密地分配实体在内存中的位置,相同的组件会被统一放在块中,读取速度快,也方便批量操作)。下面来一探究竟:

  • Main Camera ……主摄像机
  • Directional Light……光源
  • RotatingCube……旋转的方块
    • ChildCube……子方块

和案例2一样RotatingCube上同样挂了ConvertToEntity脚本,它将Unity的游戏对象GameObject转化成Entity,从而让游戏运行更加高效,脚本的工作原理已经在上一篇讲过了,此处跳过。 RotatingCube上还挂了另外一个脚本RotationSpeedAuthoring_IJobChunk,下面我们来看一下这个脚本:

[RequiresEntityConversion]
public class RotationSpeedAuthoring_IJobChunk : MonoBehaviour, IConvertGameObjectToEntity
{
    public float DegreesPerSecond = 360.0F;
    public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    {
        var data = new RotationSpeed_IJobChunk { RadiansPerSecond = math.radians(DegreesPerSecond) };
        dstManager.AddComponentData(entity, data);
    }
}

代码和上一篇的脚本RotationSpeedAuthoring_IJobForEach几乎一毛一样,区别在于Chunk关键字上了,我这里略过储存数据的RotationSpeed_IJobChunk脚本不讲,实在没有什么可说的,就储存了一个数据而已:

/// 
/// 我啥也不干,就放数据
/// 
[Serializable]
public struct RotationSpeed_IJobChunk : IComponentData
{
    public float RadiansPerSecond;
}

这里的IComponentData上次讲过,它就是一个空接口而已,作用只是表明自己是Component的身份,从而让System识别,非常纯粹的一个脚本。这里我们将理解到表明身份的重要性,下面是这个案例的重点脚本RotationSpeedSystem_IJobChunk:

/// 
/// 按块操作实体系统
/// 
public class RotationSpeedSystem_IJobChunk : JobComponentSystem
{
    EntityQuery m_Group;//查询到特定组件的实体,将其放入这个组中

    /// 
    /// 这里根据类型来查询到特定的实体
    /// 
    protected override void OnCreate()
    {
        // Cached access to a set of ComponentData based on a specific query
        ///typeof(Rotation)=带有Rotation组件的;ComponentType=对应RotationSpeed_IJobChunk组件类型的
        /// ReadOnly=只读会加快获取实体的速度,ReadWrite=读写 则相对较慢
        m_Group = GetEntityQuery(typeof(Rotation), ComponentType.ReadOnly());
    }

    // Use the [BurstCompile] attribute to compile a job with Burst. You may see significant speed ups, so try it!
    [BurstCompile]//同样使用Burst编译器来加速,区别是使用了块接口:IJobChunk
    struct RotationSpeedJob : IJobChunk
    {
        public float DeltaTime;
        /// 
        /// 原型块组件类型=Rotation
        /// 
        public ArchetypeChunkComponentType RotationType;
        /// 
        /// 只读 原型块组件类型=RotationSpeed_IJobChunk
        /// 
        [ReadOnly] public ArchetypeChunkComponentType RotationSpeedType;
        /// 
        /// 找出满足条件的实体来执行
        /// 
        /// 
        /// 块索引
        /// 第一个实体索引
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            var chunkRotations = chunk.GetNativeArray(RotationType);
            var chunkRotationSpeeds = chunk.GetNativeArray(RotationSpeedType);
            for (var i = 0; i             
关注
打赏
1664096582
查看更多评论
0.0904s