UnityECS学习日记九:Unity Job System 之 Job依赖关系

多线程开发,数据加载与计算也是在主线程基础上分前后顺序的,这里就要了解Job间的依赖关系。

JobHandle和依赖关系:

当你调用Schedule方法时会返回一个JobHandle。你可以在代码中使用JobHandle作为其他jobs的依赖关系。

组合依赖关系:

如果一个job有多个依赖项,你可以使用JobHandle.CombineDependencies方法来合并他们。CombineDependencies允许你将他们传递给Schedule方法。

在主线程中等待jobs结束:

使用JobHandle来让你的代码在主线程等待知道你的job执行完毕。为了做到这样,需要在JobHandle上调用Complete方法。这样的话,你就确定主线程可以安全访问job之前使用的NativeContainer。

便捷的扩展:

一个ParallelForTransform job是另一个类型的ParallelFor job;它是专门为了Transforms上的操作设计的。

 


案例七:IJobParallelForTransform在Job设定Transform信息(Scne8) 

 

脚本:JobParallelForTransformTest

 

using UnityEngine;
using Unity.Jobs;
using Unity.Entities;
using Unity.Collections;
using UnityEngine.Jobs;

public class JobParallelForTransformTest : MonoBehaviour
{
    struct VelocityJob : IJobParallelFor
    {
        public NativeArray<Vector3> positions;
        public NativeArray<Vector3> velocitys;
        public float delaTime;
        // 并行化 让一个线程做数组的一部分处理
        public void Execute(int index)
        {
            positions[index] = positions[index] + velocitys[index] * delaTime;
        }
    }

    // 注意这个 job扩展是定义在 UnityEngine.Jobs命名空间下
    struct ApplyTransform : IJobParallelForTransform
    {
        public NativeArray<Vector3> positions;
        public void Execute(int index, TransformAccess transform)
        {
            transform.position = positions[index];
        }
    }

    public int gameCount = 300;
    public GameObject prefab;
    public GameObject[] gameObjs;
    private TransformAccessArray tranAccessArray;      // 类似 nativeContainer 也是需要释放                     
    void Start()
    {
        gameObjs = new GameObject[gameCount];
        tranAccessArray = new TransformAccessArray(gameCount);           // 注意 这种类型数组必须将capacity主动填上  不能像list一样直接new便可以add
        for (int i = 0; i < gameCount; i++)
        {
            gameObjs[i] = Instantiate<GameObject>(prefab);
            gameObjs[i].transform.position = UnityEngine.Random.insideUnitSphere * 40;
            tranAccessArray.Add(gameObjs[i].transform);
        }

    }


    void Update()
    {
        // 1.准备数据
        NativeArray<Vector3> tmpPositions = new NativeArray<Vector3>(gameCount, Allocator.TempJob);
        NativeArray<Vector3> tmpVelocitys = new NativeArray<Vector3>(gameCount, Allocator.TempJob);
        for (int i = 0; i < gameCount; i++)
        {
            tmpVelocitys[i] = new Vector3(0, 1, 0);
            //tmpPositions[i] = tmpPositions[i] + tmpVelocitys[i] * Time.deltaTime;
            tmpPositions[i] = gameObjs[i].transform.position;
        }
        VelocityJob job = new VelocityJob()
        {
            positions = tmpPositions,
            delaTime = Time.deltaTime,
            velocitys = tmpVelocitys
        };

        //依赖按照速度计算的到的位置数组
        ApplyTransform applyTransform = new ApplyTransform()
        {
            positions = tmpPositions
        };

        // 2.执行  
        //信号量 主线程如何知道子线程执行完毕    gameCount 指定总共子线程执行数据数量 10:每个子线程以下处理多少次
        JobHandle jobHandle = job.Schedule(gameCount, 10);


        JobHandle tranHandle = applyTransform.Schedule(tranAccessArray, jobHandle);

        // 3.同步
        jobHandle.Complete();
        tranHandle.Complete();

        //4。更新位置
        //for (int i = 0; i < gameCount; i++)
        //{
        //    gameObjs[i].transform.position = tmpPositions[i];
        //}


        tmpPositions.Dispose();
        tmpVelocitys.Dispose();
    }

    private void OnDestroy()
    {
        this.tranAccessArray.Dispose();
    }
}

 

使用传统c#并不能直接跨线程访问Unity的UI,Unity便自己扩展了功能,如下图让程序方便在job中修改Transform信息(注意该结构体是在UnityEngine的核心模块里):

 

 

远程项目仓库(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、付费专栏及课程。

余额充值