首页 > 编程语言 >【Unity3D】协同程序

【Unity3D】协同程序

时间:2023-03-21 09:56:43浏览次数:79  
标签:Unity3D 协程 yield 协同程序 线程 Debug return CorutineTest

1 简介

1)协程概念

​ 协同程序(Coroutine)简称协程,是伴随主线程一起运行的程序片段,是一个能够暂停执行的函数,用于解决程序并行问题。协程是 C# 中的概念,由于 Unity3D 的渲染操作是基于帧实现的,使用线程(Thread)不便于控制,因此 Unity3D 选择使用协程实现并发效果。

​ 协程并不是取代线程,而且抽象于线程之上。线程是系统调度的基本单位,是被分割的 CPU 资源;协程是组织好的代码流程,同一时间其实只有一个协程拥有运行权,相当于单线程的能力。协程需要线程来承载运行,线程是协程的资源,但协程不会直接使用线程,协程直接利用的是执行器(Interceptor),执行器可以关联任意线程或线程池,可以是当前线程、UI线程、新建线程.。

​ 协程是一个能够暂停执行的函数,在收到中断指令后暂停执行,并立即返回主函数,执行主函数剩余的部分,直到中断指令完成后,从中断指令的下一行继续执行协程剩余的部分。函数体全部执行完成,协程结束。协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态。由于中断指令的出现,使得可以将一个函数分割到多个帧里执行。

2)中断指令

// 协程在所有脚本的FixedUpdate执行之后,等待一个fixed时间间隔之后再继续执行
yield return WaitForFixedUpdate();
// 协程将在下一帧所有脚本的Update执行之后,再继续执行
yield return null;
// 协程在延迟指定时间,且当前帧所有脚本的 Update全都执行结束后才继续执行
yield return new WaitForSeconds(seconds);
// 与WaitForSeconds类似, 但不受时间缩放影响
yield return WaitForSecondsRealtime(seconds);
// 协程在WWW下载资源完成后,再继续执行
yield return new WWW(url);
// 协程在指定协程执行结束后,再继续执行
yield return StartCoroutine();
// 当返回条件为假时才执行后续步骤
yield return WaitWhile();
// 等待帧画面渲染结束
yield return new WaitForEndOfFrame();

​ 补充:中断对象可以使用静态全局变量,避免产生过多临时对象、频繁触发 GC。

3)协程的执行周期

img

4)协程与线程的区别

  • 一个线程可以有多个协程;
  • 线程是协程的资源,协程通过 Interceptor 来间接使用线程这个资源;
  • 线程是同步机制,必须等待方法执行完才能返回执行后续方法;协程是异步机制,不需要等方法执行完就可以返回继续执行后续方法;
  • 线程是抢占式,进行线程切换,需要使用锁机制,多线程执行顺序具有一定随机性;协程是非抢占式的,多协程执行顺序由其启动顺序决定。

2 协程的使用

1)创建协程

private IEnumerator CorutineTest() {
	Debug.Log("CorutineTest, 1");
	yield return null;
	Debug.Log("CorutineTest, 2");
	yield return new WaitForSeconds(0.05f);
	Debug.Log("CorutineTest, 3");
	yield return new WaitForFixedUpdate();
	Debug.Log("CorutineTest, 4");
	yield return new WWW("https://mazwai.com/download_new.php?hash=b524357ef93c1e6ad0245c04c721e479");
	Debug.Log("CorutineTest, 5");
}

2)启动协程

private void Start() {
	// 形式一
	StartCoroutine(CorutineTest()); 
	StartCoroutine(CorutineTest("arg"));
	// 形式二, 此方式最多只能传1个参数
	StartCoroutine("CorutineTest"); 
	StartCoroutine("CorutineTest", "arg");
	// 形式三
	IEnumerator corutin = CorutineTest();
	StartCoroutine(corutin);
}

3)停止协程

public void StopCoroutine(Coroutine routine);
public void StopCoroutine(IEnumerator routine);
public void StopCoroutine(string methodName); // 只能停止用字符串方法启动的协程
public void StopAllCoroutines();
yield break; // 跳出协程

4)Start 协程

private IEnumerator Start() { // 此时程序中不能再有其他Start方法
	yield return StartCoroutine(CorutineTest());
}

3 协程的应用

1)案例一

using System.Collections;
using UnityEngine;
 
public class CorutineController : MonoBehaviour {
	private void Start() {
		Debug.Log("Start-before");
		StartCoroutine(CorutineTest(3));
        Debug.Log("Start-after");
	}
 
	private void Update() {
		Debug.Log("Update");
	}
 
	private IEnumerator CorutineTest(int count) {
		Debug.Log("CorutineTest, start");
		yield return null;
		for (int i = 0; i < count; i++) {
			Debug.Log("CorutineTest, " + i);
			yield return null;
		}
		Debug.Log("CorutineTest, end");
	}
}

​ 运行结果如下:

img

​ 从运行结果中可以看出:协程中的方法 CorutineTest 并没有阻塞 Satrt 的后续代码及 Update 方法执行。

2)案例二

​ 在 Hierarchy 窗口创建 Image 对象,并给其添加 CorutineController 脚本组件,如下:

​ CorutineController.cs

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using System.IO;

public class CorutineController : MonoBehaviour {
	private Image image;

	private void Awake() {
		image = GetComponent<Image>();
		StartCoroutine(DownLoadPicture());
	}

	private IEnumerator DownLoadPicture() {
		WWW www = new WWW("https://i0.hdslb.com/bfs/article/f04bc0a016e6d88c602047a39364a42cb27ea170.jpg@942w_531h_progressive.jpeg");
		// yield return www; // 等待www下载完毕
		while (!www.isDone) {
			Debug.Log("CorutineTest, progress = " + www.progress); // 打印下载进度
			yield return null; // 等待www下载完毕
		}
		Texture2D texture = www.texture;
		texture.name = "girl";
		image.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
		GetComponent<RectTransform>().sizeDelta = new Vector2(texture.width, texture.height);
		File.WriteAllBytes(Application.dataPath + "/CorutineScene/girl.jpeg", www.bytes); // 保存图片
	}
}

​ 运行效果:

img

​ 声明:本文转自【Unity3D】协同程序

标签:Unity3D,协程,yield,协同程序,线程,Debug,return,CorutineTest
From: https://www.cnblogs.com/zhyan8/p/17237803.html

相关文章

  • 【Unity3D】顶点和片元着色器
    1前言​上文介绍了渲染管线、固定管线着色器和表面着色器,如下:渲染管线固定管线着色器一固定管线着色器二表面着色器​固定管线着色器通过命令方式实现光......
  • 【Unity3D】表面着色器
    1前言​固定管线着色器一、固定管线着色器二中介绍了ShaderLib的基本用法,本文将接着讲解表面着色器(SurfaceShader)的用法。固定管线着色器基于ShaderLib命令实......
  • 【Unity3D】AudioSource组件
    1简介​1)AudioSource与AudioListener简介​AudioSource(音频源)组件用于控制播放AudioClip(音频片段),能够控制2D和3D(距离越远,声音越小)声音播放,它一般挂在产......
  • 【Unity3D】场景切换、全屏_恢复切换、退出游戏、截屏
    1前言​1)场景切换​场景切换可以使用SceneManager的LoadScene和LoadSceneAsync方法,如下:publicstaticvoidLoadScene(stringsceneName)publicstatic......
  • 【Unity3D】GUI控件
    1前言​Unity3D提供了GUI、NGUI、UGUI等图形系统,以增强玩家与游戏的交互性。GUI在编译时不能可视化,在运行时才能可视化。GUI代码需要在OnGUI函数中调用才能......
  • 【Unity3D】相机跟随
    1前言​相机跟随是相机指始终跟随特定游戏对象,有以下2种跟随效果:位置跟随:相机指向目标游戏对象的向量始终不变位置和姿态跟随:相机在目标游戏对象的坐标系下的坐......
  • 【Unity3D】UGUI之Text
    1Text简介​UGUI概述中介绍了Canvas渲染模式、RectTransform组件、锚点(Anchor)等,本文将介绍UGUI中的Text控件。​在Hierarchy窗口右键,选择UI列表里......
  • 【Unity3D】UGUI概述
    1UGUI与GUI区别​GUI控件在编译时不能可视化,并且界面不太美观,在实际应用中使用的较少。UGUI在编译时可视化,界面美观,实际应用较广泛。2Canvas渲染模式(Render......
  • 【Unity3D】UGUI之Button
    1Button属性面板​在Hierarchy窗口右键,选择UI列表里的Button控件,即可创建Button控件,选中创建的Button控件,按键盘【T】键,可以调整Button控件的大小和位置......
  • 【Unity3D】UGUI之Image和RawImage
    1纹理(Texture)​Image控件和RawImage控件都是承载渲染图片的控件,都需要指定一个纹理(Texture)图片。在Assets窗口选中一张图片,在Inspector窗口的参数设置面板可......