Unity扫盲:unity可以开多线程吗?

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

在很多人的印象中,都觉得unity不支持多线程,因为里面有一个协程的概念,认为协程就是因为unity不支持多线程而用的一个功能,其实这是不对的,unity是可以开多线程的,只是一般不去开线程,为什么呢?
因为游戏大多数都是单线程,而且有的游戏对于GPU的要求比较高,大多数游戏考验的是电脑CPU的单核能力,和GPU的运算能力,所以配置一台游戏主机的时候,没必要去看多核计算能力.你买的多核CPU在大多数情况下,都是单核在跑游戏逻辑.

Unity扫盲:unity可以开多线程吗?
现在就在unity中开启多线程的功能,代码简单,不必细说:

using UnityEngine;
using System.Threading;
public class testScripts : MonoBehaviour
{
    Thread t1;
    Thread t2;

    void Start()
    {
        t1 = new Thread(T1);
        t2 = new Thread(T2);
        t1.Start();
        t2.Start();
    }

    void T1()
    {
        Debug.Log("1");
    }

    void T2()
    {
        Debug.Log("2");
    }

}

运行之后会有以下2种情况:

Unity扫盲:unity可以开多线程吗?
Unity扫盲:unity可以开多线程吗?
那么为什么会有哲两种情况呢?因为线程是平行运行的,也就是说程序在开线程的时候,你的这几个线程一定是平行的关系.谁的运气好,谁就先运行,下面用一个例子来说明,这个例子的功能就是用2个线程去操作一个字符串:

using UnityEngine;
using System.Threading;
public class testScripts : MonoBehaviour
{
    Thread t1;
    Thread t2;
    string str = "";
    void Start()
    {
        t1 = new Thread(T1);
        t1.Start();
        t2 = new Thread(T2);
        t2.Start();
        Thread.Sleep();
        Debug.Log(str);
    }

    void T1()
    {
        for (int i = ; i < ; i++)
        {
            Thread.Sleep();
            str += 'a';
        }
    }

    void T2()
    {
        for (int i = ; i < ; i++)
        {
            Thread.Sleep();
            str += 'b';
        }
    }

}

由于两个线程并行执行,字符串str时而被T1操作,时而被T2操作,所以打印如下结果:
Unity扫盲:unity可以开多线程吗?
这个称之为"线程互斥"

为了避免线程竞争,可以通过加锁的方式(Lock)来处理,当2个线程争夺一个锁的时候,只能有一个线程有资格获取,另一个挂起等待。一直等到可用为止,这种情况,保证在同一时刻只有一个线程能进入临界区。程序改为下面的状态:

using UnityEngine;
using System.Threading;
public class testScripts : MonoBehaviour
{
    Thread t1;
    Thread t2;
    string str = "";
    void Start()
    {
        t1 = new Thread(T1);
        t1.Start();
        t2 = new Thread(T2);
        t2.Start();
        Thread.Sleep();
        Debug.Log(str);
    }

    void T1()
    {
        lock (str)
        {
            for (int i = ; i < ; i++)
            {
                Thread.Sleep();
                str += 'a';
            }
        }
    }

    void T2()
    {
        lock (str)
        {
            for (int i = ; i < ; i++)
            {
                Thread.Sleep();
                str += 'b';
            }
        }
    }

}

运行结果:

Unity扫盲:unity可以开多线程吗?
那么看到这里,你应该知道,unity里面是可以开多线程的了,那么为什么这么简单的东西却有很多人相信unity不能开多线程呢?因为在unity里面,不支持在新开的线程中操作UnityEngine SDK.考虑到苹果手机的单线程系统,除此之外还有其他限制,所以为了简单的教学直接就告诉别人,unity不能开多线程-_-||.其实这个是不对的.在有一些大场景加载中.或者数据比对中,开启多线程还是很有必要的(考虑到适用的场景).

如果直接在新线程中操作了UnityEngine SDK,这么用了,unity会报一个错:

can only be called from the main thread.

也就是说,你只能在主线程中操作游戏物体.所有在UnityEngin命名空间下的所有声明方法,类,皆不能在unity规定的线程之外调用它.

那么为什么要这么做呢?

游戏中逻辑更新和画面更新的时间点要求有确定性,必须按照帧序列严格保持同步,否则就会出现游戏中的对象不同步的现象.那么多线程可以吗?上文中提到的线程互斥还记得吗?那保不齐会出现什么鬼畜的动作.

其实在这里,只能说unity中不建议开启多线程,只是要考虑到平台,比如你开发一个端游,因为多线程确实不安全,如果你是做苹果端游戏,苹果就是一个单线程系统,做的假后台.你如果在苹果系统中开了新线程,那闪退是必不可少的了.

unity为了弥补开多线程的风险,unity提供了一个叫协程的功能.协程与线程的功能几乎都是一样的.协程也可以在运行期间同步执行某个代码块.

但是它们二者是有区别的,图示如下:

Unity扫盲:unity可以开多线程吗?
从图中可以看出,线程与unity主线程之间是平级关系,假如线程1直接去操作unity主线程正在操作的对象,举个例子,主线程正在控制玩家向前移动,而线程1却要控制玩家准备战斗,那么这时候,玩家该执行什么动作呢?通过线程互斥知道如果没有,如果你电脑是多核的,那么这里多线程就跑的快

Unity扫盲:unity可以开多线程吗?
协程是跑在主线程中的,这个就涉及到脚本的生命周期了

脚本继承MonoBehavior对象,会在OnStart()中做地图初始化,在Update()中进行帧刷新,然后MonoBehavior脚本可以作为一个Component挂载到某个GameObject中。

这一点点入门级的理解大致能在游戏中把地图引擎跑起来,但是并没有深入的去理解这些框架函数的执行原理。

Unity扫盲:unity可以开多线程吗?
首先,unity引擎没绘制一帧图像都要跑一遍生命周期,那么协程在里面是怎么跑的呢?

首先,协程是什么呢?总体来说,对与Unity,它是单线程的设计,它更倾向使用time slicing(时间分片)的协程(coroutine)去完成异步任务,融合到了刚刚提到的生命周期中。

要理解协程,先回顾下线程:线程是操作系统级别的概念,现代操作系统都实现并且支持线程,线程的调度对应用开发者是透明的,开发者无法预期某线程在何时被调度执行。基于此,一般那种随机出现的BUG,多与线程调度相关。

而协程Coroutine是编译器级的,本质还是一个线程时间分片去执行代码段。它通过引擎相关的代码使得代码段能够实现分段式的执行,显式调用 yield函数后才被挂起,重新开始的地方是yield关键字指定的,一次一定会跑到一个yield对应的地方。因为协程本质上还是在主线程里执行的,需 要内部有一个类似栈的数据结构,当该coroutine被挂起时要保存该coroutine的数据现场以便恢复执行。

从这点上来看,这个有点像回掉函数.当yield条件为满足时候,会一直运行协程里面的代码块.

在Unity3D中,协程是可自行停止运行 (yield),直到给定的 YieldInstruction 结束再继续运行的函数。这就好比这个条件后天性的给你一个满足.立马跳出循环.

协程 (Coroutines) 的不同用途:

yield; 在下一帧上调用所有 Update 函数后,协同程序将继续运行。

yield WaitForSeconds(2); 在指定的时间延迟之后,为此帧调用所有 Update 函数之后继续运行

yield WaitForFixedUpdate(); 在所有脚本上调用所有 FixedUpdate 后继续运行

yield WWW 完成 WWW 下载后继续运行。

yield StartCoroutine(MyFunc); 连接协同程序,并等待 MyFunc coroutine 首先结束。
也就是说,将代码段分散在不同的帧中,每次执行一段,下一帧再执行yield挂起的地方。这样看起来,就是多线程的效果.

到文末,一句话总结:

unity可以开多线程,但是不建议使用,建议使用协程.

那么,我们提到过,加载资源当然使用多线程了那么留个问题:比如程序中的Resource.Load();函数,那么这个函数加载也是在unity主线程中加载的吗?文章来源地址https://www.toymoban.com/news/detail-439723.html

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

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

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

相关文章

  • unity C# 多线程

    线程  被定义为程序的执行路径。每个线程都定义了一个独特的控制流。如果您的应用程序涉及到复杂的和耗时的操作,那么设置不同的线程执行路径往往是有益的,每个线程执行特定的工作。 线程是 轻量级进程 。一个使用线程的常见实例是现代操作系统中并行编程的实现

    2024年02月04日
    浏览(28)
  • Unity多线程和协程

    Unity支持多线程的使用,可以使用C#的Thread类来创建和管理线程,只需要引入这个类: 但需要注意的是,在Unity中,只有主线程(也称为渲染线程)可以访问Unity对象,如GameObject、Transform等,如果在其他线程中访问这些对象,会导致不可预期的结果。 因此,在使用多线程时,

    2024年02月16日
    浏览(31)
  • unity 2D中,实现点击按钮可以游戏暂停的效果

    在Unity 2D中,可以通过以下步骤和代码来设置一个按钮,实现游戏暂停的效果: 创建一个空对象,命名为\\\"GameManager\\\",用于管理游戏状态。 在GameManager对象上添加一个脚本,命名为\\\"PauseManager\\\"。 在脚本中添加以下代码: 在场景中创建一个Canvas对象,用于放置按钮。 在Canvas下创

    2024年02月03日
    浏览(38)
  • 1.Unity协程、进程、线程的区别

    1、 进程 拥有自己独立的堆和栈,堆和栈都不共享,进程由操作系统调度。 2、 线程 有自己独立的栈和共享的堆,栈不共享,堆共享,标准的线程也是由系统调度。 3、 协程 有自己独立的栈和共享的堆,栈不共享,堆共享,协程由程序员在协程的代码里面调度。 协程多与线

    2024年02月03日
    浏览(35)
  • 我的创作纪念日——一年的时间可以改变很多

    不知不觉来到CSDN已经创作一年了。打心底讲,对于在CSDN开始坚持创作的原因,我用一句话来概括最合适不过了——“无心插柳柳成荫” 为什么这么说呢? 这要从我的一篇博客说起——《输入命令Javac报错详解》: 那也是我第一次接触到Java这门语言,想必大家在最开始学习

    2023年04月08日
    浏览(28)
  • Qt扫盲-Reentrant和线程安全

    在整个文档中, Reentrant 和 thread-safe 术语用于标记类和函数,指明如何在多线程应用程序中使用它们: 一个 thread-safe的函数可以从多个线程同时调用,即使调用使用了共享数据,因为对共享数据的所有引用都是序列化的。 一个 Reentrant 函数也可以从多个线程同时调用Reentrant函

    2023年04月23日
    浏览(28)
  • unity多线程Burst+Job System

    Unity自己本身UnityEngine所使用的API是不能被多线程调用的,它没有向用户开放线程接口,所以Unity是不能使用多线程的,但是C#中可以使用多线程,Unity使用C#进行脚本编辑,故而Unity也可以通过C#来调用多线程。 JobSystem 是Unity Dots(多线程运行框架)的核心组件之一,也可以把它拿

    2024年02月04日
    浏览(28)
  • 【Unity研究】进程、线程、对象池的关系

    目录 简要概括 名词解释 实例 进程 线程 对象池 实际使用 对象池实际操作(含代码) 建立主线程以外的线程方法 在主线程中运行的生命周期 在副线程中运行的生命周期 正在运行的Unity游戏就可以看做一个进程的实例,线程是进程内的执行单元(一个进程可以拥有多个线程

    2024年02月08日
    浏览(29)
  • Unity3D开发WebAR,可以在手机上面使用

    在手机的浏览器使用unity开发的AR应用 unity在手机(ios,安卓平台)开发AR应用,已经很成熟了,但是如果想要在Web网页上面使用Ar,目前还没有很好的方法,最直接的证明方式就是ARfoudation不支持webGL 这里显示没有插件可用,所以ARfoudation不支持webGL,寻找替代品来使用。而且

    2024年02月01日
    浏览(30)
  • unity的C#学习——多线程编程(线程的生命周期、创建与管理)与线程相关类

    多线程编程是 C# 一个比较难且涵盖面比较广的知识点,本文整理仓促而且属于笔记向博客,有些地方必然还存在不严谨和错误,本人会在日后的使用过程中不断完善。如果发现问题或有改进意见可以在评论区提出,我会及时修改。 线程是程序的执行流程,也被称为 轻量级进

    2024年02月12日
    浏览(29)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包