您现在的位置是:首页 >技术交流 >unity多线程Burst+Job System网站首页技术交流

unity多线程Burst+Job System

作孽就得先起床 2024-06-17 11:19:06
简介unity多线程Burst+Job System

Unity自己本身UnityEngine所使用的API是不能被多线程调用的,它没有向用户开放线程接口,所以Unity是不能使用多线程的,但是C#中可以使用多线程,Unity使用C#进行脚本编辑,故而Unity也可以通过C#来调用多线程。

JobSystem 是Unity Dots(多线程运行框架)的核心组件之一,也可以把它拿出来利用多线程帮我们处理一些运算,比如视锥体剔除等。

在使用前需要导入:(具体自行百度下吧)

 

根据unity 官网以下几个隶属于: Unity.​Collections

这三个一般就是常用的:

IJob:

  1. 同一时间一个 Job 只能执行一个任务

IJobParallelFor

      1、同一时间执行多个相同的任务,则可以使用IJobParallelFor

IJobParallelForTransform

      1、同一时间执行多个相同的任务,专门用于操作 Transform 的 Parallel Job

IJob:执行方法示例

using Unity.Mathematics;
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
using Unity.Burst;
public class Texting : MonoBehaviour
{
    [SerializeField] private bool UseJobs = true;//控制开关
    private void Update()
   {
       float startTime = Time.realtimeSinceStartup;//游戏开始时间
       if (UseJobs)
       {
           //集合存储返回的对象
           NativeList<JobHandle> _native = new NativeList<JobHandle>(Allocator.Temp);
           for (int i = 0; i < 10; i++)
           {
               //接收返回的数据
               JobHandle jobhandle=ReallyToughTaskJob();
               //添加至集合
               _native.Add(jobhandle);
               
               //jobhandle.Complete();//等待线程完成
           }
           JobHandle.CompleteAll(_native);//等待所有线程完成
           _native.Dispose();//结束线程

       }
       else
       {
           //这里测试的是直接执行
           for (int i = 0; i < 10; i++)
           {
               ReallyToughTask();
           }
           
       }
       //输出结果
       Debug.Log((Time.realtimeSinceStartup-startTime)*1000f+"ms");
   }

   private void ReallyToughTask()
   {
       float value = 0f;
       for (int i = 0; i < 50000; i++)
       {
           value = math.exp(math.sqrt((value)));
       }
   }

   private JobHandle ReallyToughTaskJob()
   {
       //创建线程
       ReallyToughJob job = new ReallyToughJob();
       //返回结果
       return job.Schedule();
   }
   
}
[BurstCompile]//加入此标签再度提升性能
public struct ReallyToughJob:IJob  //引用类型
{
    public void Execute()
    {
        //执行的数据
        float value = 0f;
        for (int i = 0; i < 50000; i++)
        {
            value = math.exp(math.sqrt((value)));
        }
    }
}

IJobParallelFor示例:

using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
using Unity.Burst;
using Random = UnityEngine.Random;

public class Text2 : MonoBehaviour
{
    [SerializeField] private bool UseJobs = true;
    [SerializeField] private Transform pfZombie;
    private List<Zombie> zombieList;

    //用一个class类型保存数据结构
    public class Zombie
    {
        public Transform transform;
        public float moveY;
    }

    private void Start()
    {
        //创建
        zombieList = new List<Zombie>();
        for (int i = 0; i < 1000; i++)
        {
            //实例化创建1000个对象
           Transform zombieTransform= Instantiate(pfZombie,new Vector3(Random.Range(-8f,8f),Random.Range(-5f,5f),Random.Range(-10f,10f)),Quaternion.identity);
           //添加进集合 还有随机移动的y
           zombieList.Add(new Zombie
           {
               transform = zombieTransform,
               moveY = UnityEngine.Random.Range(1f,2f)
           });
        }
    }

    private void Update()
    {
        float startTime = Time.realtimeSinceStartup;//游戏开始时间

        if (UseJobs)
        {
            NativeArray<float3> positionArray = new NativeArray<float3>(zombieList.Count,Allocator.TempJob);
            NativeArray<float> moveYArray = new NativeArray<float>(zombieList.Count,Allocator.TempJob);
            
            //放入“高性能”集合中,保存数据(翻译可能有误,仅供参考)
            for (int i = 0; i < zombieList.Count; i++)
            {
                positionArray[i] = zombieList[i].transform.position;
                moveYArray[i] = zombieList[i].moveY;
            }
            //创建线程
            ReallyToughJobFor toughJobFor = new ReallyToughJobFor
            {
                //赋值给线程中的几个,提供数据
                dataTime = Time.deltaTime,
                postionArray=positionArray,
                moveYArray=moveYArray,
            };
            //开启 告知线程处理多少对象  要处理多少次
           JobHandle jobhandle= toughJobFor.Schedule(zombieList.Count,100);
           //等待线程结束
           jobhandle.Complete();
            //将返回的结果重新赋值
           for (int i = 0; i < zombieList.Count; i++)
           {
               zombieList[i].transform.position = positionArray[i];
               zombieList[i].moveY = moveYArray[i];
           }
            //删除集合
           positionArray.Dispose();
           moveYArray.Dispose();

        }
        else
        {
            //普通方法测试
            foreach (var zombie in zombieList)
            {
                zombie.transform.position += new Vector3(0, zombie.moveY * Time.deltaTime);
                if (zombie.transform.position.y>5f)
                {
                    zombie.moveY = -math.abs(zombie.moveY);
                }

                if (zombie.transform.position.y<-5f)
                {
                    zombie.moveY += +math.abs(zombie.moveY);
                }

                float value = 0f;
                for (int i = 0; i < 1000; i++)
                {
                    value = math.exp10(math.sqrt(value));
                }
            }
        }
        //输出结果
        Debug.Log((Time.realtimeSinceStartup-startTime)*1000f+"ms");
    }
    
    
}
[BurstCompile]//加入此标签再度提升性能,使得计算转为LR,提升运行效率
public struct ReallyToughJobFor:IJobParallelFor  //引用类型
{
    //创建集合
    public NativeArray<float3>  postionArray;
    public NativeArray<float> moveYArray;
    public float dataTime;
    //index 获取执行次数
    public void Execute(int index)
    {
        //具体执行方案
        postionArray[index] += new float3(0, moveYArray[index] * dataTime,0f);
        if (postionArray[index].y>5f)
        {
            moveYArray[index] = -math.abs(moveYArray[index]);
        }

        if (postionArray[index].y<-5f)
        {
            moveYArray[index] += +math.abs(moveYArray[index]);
        }

        float value = 0f;
        for (int i = 0; i < 1000; i++)
        {
            value = math.exp10(math.sqrt(value));
        }
    }
}

IJobParallelForTransform示例:

using System;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
using Unity.Jobs;
using Unity.Collections;
using Unity.Burst;
using UnityEngine.Jobs;
using Random = UnityEngine.Random;

public class Text3 : MonoBehaviour
{
   [SerializeField] private bool UseJobs = true;
    [SerializeField] private Transform pfZombie;
    private List<Zombie> zombieList;

    //创建集合
    public class Zombie
    {
        public Transform transform;
        public float moveY;
    }

    private void Start()
    {
        zombieList = new List<Zombie>();
        for (int i = 0; i < 1000; i++)
        {
           Transform zombieTransform= Instantiate(pfZombie,new Vector3(Random.Range(-8f,8f),Random.Range(-5f,5f),Random.Range(-10f,10f)),Quaternion.identity);
           
           
           zombieList.Add(new Zombie
           {
               transform = zombieTransform,
               moveY = UnityEngine.Random.Range(1f,2f)
           });
        }
    }

    private void Update()
    {
        float startTime = Time.realtimeSinceStartup;//游戏开始时间

        if (UseJobs)
        {
            //创建Transfrom集合
            TransformAccessArray _array = new TransformAccessArray(zombieList.Count);
            NativeArray<float> moveYArray = new NativeArray<float>(zombieList.Count,Allocator.TempJob);

            //添加
            for (int i = 0; i < zombieList.Count; i++)
            {
                _array.Add(zombieList[i].transform);
                moveYArray[i] = zombieList[i].moveY;
            }
            
            //创建多线程
            ReallyToughJobForTransfrom _tough = new ReallyToughJobForTransfrom
            {
                //赋值
                dataTime = Time.deltaTime,
                moveYArray=moveYArray,
            };
            
            //开启 传入对象集合
           JobHandle jobhandle= _tough.Schedule(_array);
           //等待完成
           jobhandle.Complete();

           //返回结果,重新赋值
           for (int i = 0; i < zombieList.Count; i++)
           {
               zombieList[i].moveY = moveYArray[i];
           }
           
           //清空关闭集合
           moveYArray.Dispose();
           _array.Dispose();
        }
        else
        {
            //普通执行
            foreach (var zombie in zombieList)
            {
                zombie.transform.position += new Vector3(0, zombie.moveY * Time.deltaTime);
                if (zombie.transform.position.y>5f)
                {
                    zombie.moveY = -math.abs(zombie.moveY);
                }

                if (zombie.transform.position.y<-5f)
                {
                    zombie.moveY += +math.abs(zombie.moveY);
                }

                float value = 0f;
                for (int i = 0; i < 1000; i++)
                {
                    value = math.exp10(math.sqrt(value));
                }
            }
        }
        
        Debug.Log((Time.realtimeSinceStartup-startTime)*1000f+"ms");
    }
    
}
[BurstCompile]
public struct ReallyToughJobForTransfrom:IJobParallelForTransform  //引用类型
{
    
    public NativeArray<float> moveYArray;
    public float dataTime;
    
    //获取对象 Transfrom对象
    public void Execute(int index,TransformAccess access )
    {
        //具体方法
        access.position += new Vector3(0, moveYArray[index] * dataTime,0f);
        if (access.position.y>5f)
        {
            moveYArray[index] = -math.abs(moveYArray[index]);
        }

        if (access.position.y<-5f)
        {
            moveYArray[index] += +math.abs(moveYArray[index]);
        }

        float value = 0f;
        for (int i = 0; i < 1000; i++)
        {
            value = math.exp10(math.sqrt(value));
        }
    }
}

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。