美文网首页Unity探路营
【实战】使用Job来修改Transform

【实战】使用Job来修改Transform

作者: 洪智 | 来源:发表于2020-09-20 16:32 被阅读0次

    洪流学堂,让你快人几步。你好,我是跟着大智学Unity的萌新,我叫小新,最近在跟着大智探索DOTS。

    上一节咱们学习了ParallelFor Job,也称为并行Job,可以根据传入的数据量,批量同时执行。在Unity中,咱们通常会进行大量修改的其实是物体的Transform,比如位置、旋转等等。

    对于Transform的修改,Job System中有一个专属的Job,叫做ParallelForTransform Job,这种Job需要实现IJobParallelForTransform接口。

    Job代码例如:
    这个job是基于速度和deltaTime来更新Transform的位置

        struct PositionUpdateJob : IJobParallelForTransform
        {
            // 给每个物体设置一个速度
            [ReadOnly]
            public NativeArray<Vector3> velocity;
    
            public float deltaTime;
    
            // 实现IJobParallelForTransform的结构体中Execute方法第二个参数可以获取到Transform
            public void Execute(int i, TransformAccess transform)
            {
                transform.position += velocity[i] * deltaTime;
            }
        }
    

    其中和ParallelFor Job不一样的地方在Execute方法中,第二个参数可以获取到Transform中的数据。

    此外,在调度这个Job时,需要传入一个TransformAccessArray,也就是需要执行的多个Transform的native数组。具体构造方法如下:

    var transforms = new Transform[10000];
    // TODO 此处应该去获取所有物体的Transform组件,并放到数组中
    var transformsAccessArray = new TransformAccessArray(transforms);
    
    // 实例化一个job,传入数据
    m_Job = new PositionUpdateJob()
    {
        deltaTime = Time.deltaTime,
        velocity = m_Velocities,
    };
    
    m_Job.Schedule(m_TransformsAccessArray);
    

    这个Job其他使用的写法基本和之前类似,咱们直接通过一个完整的实战代码来学习。

    using Unity.Collections;
    using Unity.Jobs;
    using UnityEngine;
    using UnityEngine.Jobs;
    
    public class TransformJobs : MonoBehaviour
    {
        // 用于存储transform的NativeArray
        private TransformAccessArray m_TransformsAccessArray;
        private NativeArray<Vector3> m_Velocities;
    
        private PositionUpdateJob m_Job;
        private JobHandle m_PositionJobHandle;
    
        struct PositionUpdateJob : IJobParallelForTransform
        {
            // 给每个物体设置一个速度
            [ReadOnly]
            public NativeArray<Vector3> velocity;
    
            public float deltaTime;
    
            // 实现IJobParallelForTransform的结构体中Execute方法第二个参数可以获取到Transform
            public void Execute(int i, TransformAccess transform)
            {
                transform.position += velocity[i] * deltaTime;
            }
        }
    
        void Start()
        {
            m_Velocities = new NativeArray<Vector3>(10000, Allocator.Persistent);
    
            // 用代码生成一个球体,作为复制的模板
            var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            // 关闭阴影
            var renderer = sphere.GetComponent<MeshRenderer>();
            renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
            renderer.receiveShadows = false;
    
            // 关闭碰撞体
            var collider = sphere.GetComponent<Collider>();
            collider.enabled = false;
    
            // 保存transform的数组,用于生成transform的Native Array
            var transforms = new Transform[10000];
            // 生成1W个球
            for (int i = 0; i < 100; i++)
            {
                for (int j = 0; j < 100; j++)
                {
                    var go = GameObject.Instantiate(sphere);
                    go.transform.position = new Vector3(j, 0, i);
    
                    transforms[i*100+j] = go.transform;
                    m_Velocities[i * 100 + j] = new Vector3(0.1f * j, 0, 0.1f * j);
                }
            }
    
            m_TransformsAccessArray = new TransformAccessArray(transforms);
        }
    
        void Update()
        {
            // 实例化一个job,传入数据
            m_Job = new PositionUpdateJob()
            {
                deltaTime = Time.deltaTime,
                velocity = m_Velocities,
            };
    
            // 调度job执行
            m_PositionJobHandle = m_Job.Schedule(m_TransformsAccessArray);
        }
    
        // 保证当前帧内Job执行完毕
        private void LateUpdate()
        {
            m_PositionJobHandle.Complete();
        }
    
        // OnDestroy中释放NativeArray的内存
        private void OnDestroy()
        {
            m_Velocities.Dispose();
            m_TransformsAccessArray.Dispose();
        }
    }
    

    总结

    以上代码实现了对多个GameObject物体位置的修改。

    扩展阅读

    【扩展学习】洪流学堂回复DOTS可以阅读本系列所有文章,更有视频教程等着你!


    呼~ 今天小新絮絮叨叨的真是够够的了。没讲清楚的地方欢迎评论,咱们一起探索。

    我是大智,你的技术探路者,下次见!

    别走!点赞收藏哦!

    好,你可以走了。

    相关文章

      网友评论

        本文标题:【实战】使用Job来修改Transform

        本文链接:https://www.haomeiwen.com/subject/ohyoektx.html