Unity自己本身UnityEngine所使用的API是不能被多线程调用的,它没有向用户开放线程接口,所以Unity是不能使用多线程的,但是C#中可以使用多线程,Unity使用C#进行脚本编辑,故而Unity也可以通过C#来调用多线程。
JobSystem 是Unity Dots(多线程运行框架)的核心组件之一,也可以把它拿出来利用多线程帮我们处理一些运算,比如视锥体剔除等。
在使用前需要导入:(具体自行百度下吧)
根据unity 官网以下几个隶属于: Unity.Collections
这三个一般就是常用的:
IJob:
- 同一时间一个 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));
}
}
}