UnityECS学习日记十二:Unity Job System中IJobChunk的使用

内存块(IJobChunk),这个块是被一开始基于相同原型分配好了的,也就是说,如果实体有相同的组件,那么他们会被紧密的安排在一块内存中,从而方便处理器进行操作。这是相对于面向对象的散列内存而言的,在面向对象中要操作内存中的某个对象时,你不得不在整个内存中寻找它,这样会降低读取速度,也不方便批量操作。ECS则会非常紧密地分配实体在内存中的位置,相同的组件会被统一放在块中,读取速度快,也方便批量操作。

块的概念必读:http://www.benmutou.com/archives/2805


案例十:Job使用内存块(JobChunk)来模拟雨滴下落(Scne11)

注意:在使用哪个场景的使用将其 ComponentSystem的 [DisableAutoCreation] 去掉,这个是同来停止 系统功能的!

脚本:IJobChunk_DropData

using Unity.Entities;

public struct IJobChunk_DropData : IComponentData
{
    public float delay;
    public float velocity;
}

脚本:IJobChunk_Main

using UnityEngine;
using Unity.Entities;
using Unity.Collections;
using Unity.Transforms;

public class IJobChunk_Main : MonoBehaviour
{


    public int entityCount = 1000;
    public int entityRange = 100;
    public GameObject prefab;

    private EntityManager entityManager;
    private NativeArray<Entity> entityArray;
    void Start()
    {
        this.CreatePureMain();
    }

    void CreatePureMain()
    {

        entityManager = World.Active.EntityManager;

        entityArray = new NativeArray<Entity>(entityCount, Allocator.Persistent);

        Entity entity = GameObjectConversionUtility.ConvertGameObjectHierarchy(this.prefab, World.Active);

        entityManager.Instantiate(entity, entityArray);

 
        for (int i = 0; i < entityCount; i++)
        {
            // 初始化位置信息
            Translation translation = new Translation();
            translation.Value = Random.insideUnitSphere * entityRange;                      // 设置位置为随机的球体
            translation.Value.y = 0;
            entityManager.SetComponentData<Translation>(entityArray[i], translation);  // 设置位置信息

            // 初始化延迟时间
            entityManager.AddComponentData<IJobChunk_DropData>(entityArray[i], new IJobChunk_DropData {  delay=5, velocity=10});

            
        }

    }

    private void OnDestroy()
    {
        entityArray.Dispose();     // 这里把内存缓冲区释放掉
    }

}

脚本:IJobChunk_TranJobComponent

using UnityEngine;
using UnityEngine.Jobs;
using Unity.Entities;
using Unity.Jobs;
using Unity.Transforms;
using Unity.Collections;
using Unity.Burst;
[DisableAutoCreation]
public class IJobChunk_TranJobComponent : JobComponentSystem
{
    EntityQuery entityQuery;
    protected override void OnCreate()
    {
        entityQuery = this.GetEntityQuery(typeof(Translation), typeof(IJobChunk_DropData));
    }
    [BurstCompile]
    struct TranslateJob : IJobChunk
    {
        [ReadOnly]
        public float deltaTime;
        [ReadOnly]
        public int minHeight;
        [ReadOnly]
        public float velocity;
        [ReadOnly]
        public float delay;
        public ArchetypeChunkComponentType<Translation> archetypeTranslation;
        public ArchetypeChunkComponentType<IJobChunk_DropData> archetypeDropData;

        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            // 通过原型从块里获取对应的实体数组
            var tranArray = chunk.GetNativeArray<Translation>(archetypeTranslation);
            var dropArray = chunk.GetNativeArray<IJobChunk_DropData>(archetypeDropData);

            for (int i = 0; i < chunk.Count; i++)
            {
                var dropData = dropArray[i];
                var translation = tranArray[i];
                if (dropData.delay > 0)
                {
                    dropData.delay -= deltaTime;
                }
                else
                {
                    if (translation.Value.y < minHeight)
                    {
                        translation.Value.y = 0;
                        dropData.velocity = velocity;
                        dropData.delay = delay;
                    }
                    else
                    {
                        translation.Value.y -= dropData.velocity * deltaTime;
                    }
                }
                dropArray[i] = dropData;
                tranArray[i] = translation;
            }

        }
    }


    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        // 获取相对应组件的原型
        var tranArchetype = this.GetArchetypeChunkComponentType<Translation>();
        var dropArachetype = this.GetArchetypeChunkComponentType<IJobChunk_DropData>();
        
        TranslateJob translateJob = new TranslateJob()
        {
            deltaTime = Time.deltaTime,
            minHeight = -70,
            archetypeTranslation = tranArchetype,
            archetypeDropData = dropArachetype,
            delay = UnityEngine.Random.Range(1, 10),
            velocity = UnityEngine.Random.Range(1, 10),
        };
        // 注意这里的筛选器中对应的组件必须和job中对应的相同
        
        JobHandle outputDeps = translateJob.Schedule(entityQuery, inputDeps);
        return outputDeps;
    }


}

IJobChunk使用的时候是在OnUpdate中是对块进行赋值操作的,而IJobForEach是对每个实体进行操作的,从而提高游戏性能!IJobChunk帧率更高一些。

本文参考:https://blog.csdn.net/qq_30137245/article/details/99068336 

远程项目仓库(github):https://github.com/h1031464180/UnityECS 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity ECS(Entity Component System)是Unity引擎的一种编程范式,它是一种数据驱动的编程模型,它将游戏对象(Entity)分解为数据和行为两个部分,其数据由组件(Component)来表示,行为则由系统(System)来实现。相对于传统的面向对象编程模型,ECS提供了更高效、更灵活的编程方式,可以有效地提高游戏的性能和扩展性。 下面是我学习Unity ECS时的笔记: ## Entity Entity是ECS最基本的概念,它表示游戏对象。每个Entity由一个唯一的ID来标识,可以通过EntityManager来创建、销毁、查询和管理Entity。 ## Component Component是Entity的数据部分,用来描述Entity的属性和状态。每个Component包含一些数据成员和一些方法,用来操作这些数据成员。Component是以结构体(struct)的形式定义的,通常只包含数据成员,不包含方法。 ## System System是Entity的行为部分,用来实现游戏逻辑和操作Component。System可以访问和操作EntityManager和Component,但不能直接访问Entity。每个System包含一个或多个Component,表示它所处理的数据类型。System是以类(class)的形式定义的,通常包含一个Update方法,用来实现游戏逻辑。 ## Job Job是一种轻量级的线程,用于并行执行System的任务。Job可以访问和操作Component,但不能直接访问Entity和EntityManager。Job通常是以结构体(struct)的形式定义的,不包含方法。 ## Archetype Archetype是Entity的集合,包含一组具有相同Component类型的Entity。Archetype可以用来优化数据的访问和处理,可以在不同的System之间共享。 ## Chunk Chunk是Archetype的数据块,包含一组连续的Entity和它们的Component数据。Chunk可以用来优化内存的分配和访问,可以在Job进行并行处理。 ## Buffer Buffer是一种Component类型,用来存储可变长度的数据,例如数组或列表。Buffer可以在System和Job进行修改和访问。 以上是我学习Unity ECS时的笔记,希望对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值