unity多线程Burst+Job System

这篇具有很好参考价值的文章主要介绍了unity多线程Burst+Job System。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

我个人注意到,有不少案例在Update中进行使用,这里特别提示,这是不合法的,虽然这么使用确实可以运行,但操作起来非常不灵活,如非必要请不要这样做。

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

burstcompile+jobsystem+aoi,unity,c#,游戏引擎

根据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示例:文章来源地址https://www.toymoban.com/news/detail-765396.html

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));
        }
    }
}

到了这里,关于unity多线程Burst+Job System的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 「Unity3D」解决2022的PackageManager无法显示官方插件Burst和Collections的最新版本

    非常奇怪Unity2022版本的 PackageManager 无法显示 Burst 和 Collections 的最新版本,但是官方文档已经 release 了更高的适配版本,如下图: 实际上,在2020或2021版本中,可以看到两者的最新版本是 1.8.2 和 1.4.0 ,并且可以正确安装。 那么解决的办法就是,手动添加 packages.unity.com 到

    2024年02月07日
    浏览(73)
  • Unity学习笔记:Job system

    Unity的job system可以让我们编写简单且安全的多线程代码,从而让我们的游戏可以使用所有可用的CPU内核来执行代码。这样可以提升我们的游戏的性能。 Unity的job system可以帮助我们写出多线程代码,从而我们的游戏可以使用所有可用的CPU内核来执行代码。job system为我们提供了

    2024年02月20日
    浏览(33)
  • 【爬虫】AOI

    目前几个大厂,高德百度腾讯,都支持POI爬取,而AOI是需要自己找接口的。 换言之,爬虫需谨慎 参考链接是: 这两个链接是选定范围爬取范围内选定类别的AOI 黑科技 | 百度地图抓取地块功能(上) 黑科技 | 百度地图获取地块功能属性(下) 而这个链接是用名称爬取。我参

    2024年02月13日
    浏览(26)
  • AOI与AVI:在视觉检测中的不同点和相似点

    AOI(关注区域)和AVI(视觉感兴趣区域)是视觉检测中常用的两个概念,主要用于识别和分析图像或视频中的特定区域。虽然这两个概念都涉及到注视行为和注意力分配,但它们在定义和实际应用等方面有一些差异。 AOI通常是指图像或视频中用户或观察者的关注区域,主要用

    2024年01月20日
    浏览(40)
  • Burst(突发)传输

    Burst传输,可以翻译为突发传输或者是连续传输。是指在同一行中相邻的存储单元连续进行数据传输的方式,只要指定起始地址和突发长度(Burst lengths,可以理解为跨度),控制器就会依次自动对后面相同数量的存储单元进行读/写操作,而不需要控制器连续提供列地址 内存

    2024年02月07日
    浏览(30)
  • x86游戏逆向之实战游戏线程发包与普通发包的逆向

    网游找Call的过程中难免会遇到不方便通过数据来找的或者仅仅查找数据根本找不到的东西,但是网游中一般的工程肯定要发给服务器,比如你打怪,如果都是在本地处理的话就特别容易产生变态功能,而且不方便与其他玩家通信,所以找到了游戏发包的地方,再找功能就易如

    2024年02月06日
    浏览(46)
  • Hadoop云计算助力企业实现云burst

    作者:禅与计算机程序设计艺术 “云burst”是指利用云计算平台快速启动、部署及扩展大规模集群系统资源。由于高成本,IT部门经常面临着扩容困难,需求急剧增加,而资源不足问题更是无法缓解,因此如何在云计算平台上高效快速地处理并释放资源成为企业IT部门面临的重

    2024年02月07日
    浏览(36)
  • 【CompletableFuture任务编排】游戏服务器线程模型及其线程之间的交互(以排行榜线程和玩家线程的交互为例子)

    需求: 1.我们希望玩家的业务在玩家线程执行,无需回调,因此是多线程处理。 2.匹配线程负责匹配逻辑,是单独一个线程。 3.排行榜线程负责玩家的上榜等。 4.从排行榜线程获取到排行榜列表后,需要给玩家发奖修改玩家数据,因此涉及到排行榜线程和玩家线程的交互。

    2024年01月22日
    浏览(47)
  • Android性能优化之游戏收敛线程,减少OOM发生(epic 检测线程调用/booster减少常驻线程超时销毁)

    先来了解下一个空白app的进程中线程数量 : 分析迷你世界中app线程之前,先来了解下空白app ,中线程情况: 一个空白app的线程大概是27个: 一个空白的的app,包含FinalizerDaemon线程、FinalizerWatchd线程、RenderThread、主线程、ReferenceQueued、HeapTaskDaemon、SignalCatcher、GCDaemon、hwuiTa

    2024年02月14日
    浏览(87)
  • 【C++】做一个飞机空战小游戏(四)——给游戏添加背景音乐(多线程技巧应用)

      [导读]本系列博文内容链接如下: 【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动 【C++】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C++】做一个飞

    2024年02月14日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包