Unity 协程与线程区别

1、协程 不是 线程,协同程序是
不同步 的

一个线程在程序中和其他线程是异步运行的,在多处理器机器中一个线程可以同时与所有其他线程的实时运行其代码,这使得线程编程能够解决很复杂的事情,因为可能在相同的时间里一个线程在改变它而另一个线程正在读取它,这意味着另一个线程实际上可以改变的东西在游戏中处理的中间似乎是你的源代码一行。这是因为你写的代码是由机器变成汇编语言,更是更复杂。正因为如此,你必须通过锁,以确保这种情况不会由任何确保没有共享内存发生。或者通过锁定其他线程使用同一块内存,当他们在读取或更改时。

2、什么是协程?

协同程序绝对不是一个线程。这意味着在同一时间只有一个协同程序在执行,它会被执行在游戏的主线程上,所以实际上在同一时间游戏的核心只有一个协同程序在运行[这段翻译的不太好]

     你永远不需要担心同步或锁定一个值当你正在编写一个协同程序。你有完全的控制权,直到你的代码执行到
yiedld

因此总结一下协程的定义

   
协程只是部分执行,并假定在适当的条件得到满足,在未来的某一时刻将被恢复,直到它的工作完成

Unity processes coroutines every frame of the game for every object that has
one or more running.  The processing occurs after Update and before
LateUpdate for most yield statements, but there are special cases:

Unity的流程协同程序在游戏的每一帧每个对象为具有一个或多个正在运行的。Update() 之后,LateUpdate()之前 ,发生的 yield
语句的处理,但也有特殊情况

When the coroutine is activated it will execute right up to the next yield
statement and then it will pause until it is resumed.  You can see where it
will resume in the diagram above, based on what you yield.

当协程被激活,它会一直到下一个 yield语句执行,然后它会暂停,直到它恢复。你可以在上图中看到它会恢复,根据你的 yield语句

让我们来看看一个非常简单的协程

IEnumerator TestCoroutine()
{
while(true)
{
Debug.Log(Time.time);
yield return null;
}
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

该协程将会永远执行下去。它记录当前的时间,然后yield,当它被恢复,它又进入了这个循环,记录一次时间,遇到 yield 并重复之前的操作

The code inside the loop is exactly like an Update
function.  It runs once every frame for this object, just after the
script‘s Update routine runs (if it has one).

这代码循环就像 Update() 函数。这个对象在每一帧中运行,脚本的Update 程序运行后(如果有的话)

When you call StartCoroutine(TestCoroutine()) the code executes immediately
up to the first time it yields, it will then be resumed when Unity processes
coroutines for this object.

当你调用 StartCoroutine(TestCoroutine()) 代码立即第一次得到执行 然后 yield,当Unity
引擎再次处理这个GameObject时,协程会被恢复

If you start a coroutine early in the processing of a
game object, like creating one in Start, Update or OnCollisionEnter then that
coroutine will immediately run up to the first yield, then it will resume during
the same frame if you yield return null .

如果你在早于Unity处理到GameObject就执行一个协程 比如
Start(),Update()或OnCollisionEnter()将会继续执行,当第一次遇到yield,然后同一帧会恢复,如果你yield
null。有时候会有奇怪的结果,如果你不考虑它。

是否会无限循环

现在还有一件事,在我们的测试协程显然不是无限循环

下列情况协程将会不再被执行:如果你拨打电话,会停止游戏对象的协同程序,如果它被销毁,它不会再次运行。如果脚本被直接或通过游戏对象上使用SetActive(false),它也不会再执行。

I Yield Sir

Unity processes coroutines every frame of the game for every object that has
one or more running.

Unity在处理协程时是 在游戏的每一帧,每一个GameObject上进行的,可以处理1个或多个

你也许也想哦,不,它不需要,如果你使用这样的

yield return new WaitForSeconds(1)
then it doesn‘t process it for another 1 second!"
那么它不处理它的另外1秒
Well actually Unity does process that coroutine every frame, checking to see if the right amount of time has elapsed - it doesn‘t process your code, but it does process the coroutine which is the wrapper its made around your script.
那么实际上,Unity 会处理协程在每一帧,检查合适的时间是否已经过去,它不会处理你的代码,但是它会处理这个协程,是你的脚本在包装这个协程
因此我们知道,我们可以有效的暂停我们的代码通过 yield ,下面是那些你可以Return 的:

  • null -协程执行下一次,它是合格的

  • WaitForEndOfFrame - 协程的框架上执行,在所有的渲染和图形用户界面完成之后

  • WaitForFixedUpdate - 导致此协程在下一次物理学的步骤执行,在所有的物理计算之后

  • WaitForSeconds - 使协程并不是一个特定的游戏时间内执行

  • WWW - waits for a web request to complete (resumes as if WaitForSeconds or null)

  • Another coroutine - in which case the new coroutine will run to completion before the yielder is resumed(在这种情况下,新的协同程序将在这个Yield恢复之前完成)
You can also issue the command yield break; which immediately stops the coroutine.你还可以发出 yield break 命令,去立即停止这个协程
Because of WaitForEndOfFrame coroutines can be used to get information from render textures when all cameras have completed rendering and the GUI has been displayed
因为 WaitForEndOfFrame 协程可以用于从渲染纹理中获取信息, 当所有的Camera已完成渲染 并且 GUI 已经被显示
Using yield return new WaitForSeconds(x) will never resume if the Time.timeScale is set to 0.
采用 yield return new WaitForSeconds(x) 将永远不会被恢复,如果 Time.timeScale =0
Of course the great thing about all of this is that you can write code that needs to execute over a period of time, or wait for some external event to occur, and keep it all nicely together in a single function making your code far more readable than if you had to write multiple functions or lots of code to keep checking the state of things.
当然,关于这一切的伟大的事情是,你可以写需要执行一段时间,或者等待发生一些外部事件,并保持它拥有时尚典雅的一起在一个单一的功能使你的代码更易读的代码比,如果你不得不编写多个函数的代码或地段继续检查事物的状态。这是真正的协同程序的地步。
 
总结:

  1. Coroutines are a really good way of making a
    sequence of operations happen over time or when some external process is
    completed
  2. Coroutines are not threads and are not
    asynchronous
  3. Nothing else is running when your coroutine is
    executing
  4. Your coroutine will resume when the conditions
    of your yield statement are met
  5. Coroutines are inactive when the script is
    disabled or the object is destroyed
  6. yield return new WaitForSeconds
    is dependent on game time which is affected by Time.timeScale

译:

  1. 协程通过按顺序的操作 或一些其实的处理 当它完成时
  2. 协程并不是线程,它没有同步
  3. 没有任何 或已经在运行协程
  4. 你的协程

协程的实际用途

希望我们已经理解了协程是什么,以及它们在运行时。我们的高级教程将研究该技术在它们身后

让我们用协程做一些事情。几个简单的辅助函数,使用协程可以让我们创建易于切割的序列

我们可以写一个协同的移动对象到目标位置和旋转。我们可以写一个协程的等待动画是一个特定的完成百分比。然后利用这两个工具,
我们可以很容易地编写脚本在一个单一的功能,其中它会很容易阅读全切序列

使用协程,通过观看它在移动,为的是要确保不会有其它的协程或Update()函数里更改它的位置在同一时间确保你只有一个协程影响GameObject在同一时间,禁用Update() 函数 移动对象

这里有一个协同的一个例子等待动画部分完成

//Wait for an animation to be a certain amount complete
IEnumerator WaitForAnimation(string name, float ratio, bool play)
{
//Get the animation state for the named animation
var anim = animation[name];
//Play the animation
if(play) animation.Play(name);

//Loop until the normalized time reports a value
//greater than our ratio. This method of waiting for
//an animation accounts for the speed fluctuating as the
//animation is played.
while(anim.normalizedTime + float.Epsilon + Time.deltaTime < ratio)
yield return new WaitForEndOfFrame();

}


.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

You could write a coroutine to wait for an animation like this:

IEnumerator Die()
{
//Wait for the die animation to be 50% complete
yield return StartCoroutine(WaitForAnimation("die",0.5f, true));
//Drop the enemies on dying pickup
DropPickupItem();
//Wait for the animation to complete
yield return StartCoroutine(WaitForAnimation("die",1f, false));
Destroy(gameObject);
}
 
原文:http://unitygems.com/coroutines/

时间: 2024-10-12 15:21:18

Unity 协程与线程区别的相关文章

Unity协程(Coroutine)原理深入剖析再续

Unity协程(Coroutine)原理深入剖析再续 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 前面已经介绍过对协程(Coroutine)的认识和理解,主要讲到了Unity引擎在执行协程(Coroutine)的原理(Unity协程(Coroutine)原理深入剖析)和对协程(Coroutine)状态的控制(Unity协程(Coroutine)管理类--TaskManager工具分享),到这使用Coroutine的疑问就没有了,但是D

Unity协程(Coroutine)原理深入剖析(转载)

记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程,当时有点懵,完全不知道Unity协程的执行机制是怎么样的,只是知道函数的返回值是IEnumerator类型,函数中使用yield return ,就可以通过StartCoroutine调用了.后来也是一直稀里糊涂地用,上网google些基本都是例子,很少能帮助深入理解Unity协程的原理的. 本文只是从Unity的角度去分析理解协程的内部运行原理,而不是从C#底层的语法实现来介绍(后续有需要再进行介绍),一共分为三部分: 线程(

Unity协程(Coroutine)原理深入剖析

尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程,当时有点懵,完全不知道Unity协程的执行机制是怎么样的,只是知道函数的返回值是IEnumerator类型,函数中使用yield return ,就可以通过StartCoroutine调用了.后来也是一直稀里糊涂地用,上网google些基本都是例子,很少能帮助深入理解Unity协程的原理的. 本文只是从Unity的角度去分析理解协程的内部运行原理

Unity 协程深入解析与原理

先来直接放一段代码 1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 public class CoroutineTest : MonoBehaviour 6 { 7 8 void Start() 9 { 10 Debug.Log("Start Begin"); 11 12 CustomCoroutine = DelayPrint("Hi"

【转】Unity协程(Coroutine)原理深入剖析

Unity协程(Coroutine)原理深入剖析 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程,当时有点懵,完全不知道Unity协程的执行机制是怎么样的,只是知道函数的返回值是IEnumerator类型,函数中使用yield return ,就可以通过StartCoroutine调用了.后来也是一直稀里糊涂地用,上网google些基本都是例子,很少能帮助深入理解Unit

爬虫协程比线程爬取速度更快?

先做个小示例,不用废话谈理论,没有实践的空谈都是扯蛋误导人. # coding=utf-8 import requests,time count=0 urlx= 'http://www.xxsy.net/' # 'http://www.danmeila.com/' http://www.sina.com.cn/ 'http://www.qingkan9.com/' # # 'http://www.qingkan9.com/' def fun(url): try: print url resp=r

Unity 协程使用指南

0x00 前言 在使用Unity的过程中,对协程只知道如何使用,但并不知道协程的内部机理,对于自己不清楚的部分就像一块大石压力心里,让自己感觉到担忧和不适.这篇文章一探究竟,彻底揭开协程的面纱,让大家在使用中不再有后顾之忧. 0x01 概念 协程是:程序组件来生成非抢占式多任务子函数,生成的子函数允许在程序里挂起和唤醒操作. 0x02 使用场景 通常协程可以很方便实现延时操作,以及异步加载操作.下面是两个简单协程使用例子. 延时操作 // Use this for initialization

unity3D中协程和线程混合

这是我google unity3D一个问题偶然发现的在stackflow上非常有趣的帖子: 大意是 要在unity3D上从server下载一个zip,并解压到持久化地址.并将其载入到内存中.以下展示了这样的使用方法: IEnumerator LongCoroutine() { yield return StartCoroutine(DownloadZip()); ExtractZip(); yield return StartCoroutine(LoadZipContent()); } 可是Ex

Unity协程(Coroutine)管理类——TaskManager工具分享

Unity协程(Coroutine)管理类--TaskManager工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 在分享vp_Timer 中提到,没有继承的MonoBehaviour,没有Update,InVoke 和StartCoroutine的机制,vp_Timer就是提供了InVoke的机制,而且还可以统一管理.本篇D.S.Qiu要分享的TaskManager就是一个协程 管理类. TaskManager -- Unit