【妙用协程】 - 协程甚至能用来做动画

本文介绍如何在Unity3D游戏引擎中利用C#的协程控制动画效果,通过具体的代码示例展示了如何实现动画的暂停、继续及等待特定动画阶段的功能,这种方法有助于提高代码的可读性和维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

协程用途广泛,甚至可以用来控制动画效果。在手游时代著名的游戏引擎Unity 3D内置了C#作为脚本语言的支持。C#有和Python的generator几乎一样的语法(叫做Enumerator),而C#的Enumerator在Unity 3D被用作控制一个动画的过程的工具。本文是 http://unitygems.com/coroutines/ 这篇文章的一个摘要。
协程是一个可被中断然后又被继续的函数执行过程,在Unity 3D中,这个继续又中断的动机就是动画是一帧一帧的(Frame)。控制动画的协程会在每一帧中被执行一下,然后又被中断,然后又在下一帧中继续,如此往复:
请输入图片描述

代码写出来就是这个样子的:

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

}

Die函数控制了一个动画人物的死亡过程。yield了之后,函数就不在被执行了,直到yield的子协程执行完了,引擎才会继续执行yield后面的动画动作。而其中的WaitForAnimation的子协程是真正细化到每一帧的动画播放过程了:

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

}

把代码用协程这样写的好处是什么?就是Logic Locality,前后相关的逻辑放在一个函数内,比分散在多个回调函数中要更容易理解。

### Unity 中线程与协程的使用及区别 #### 1. 协程 (Coroutine) 的基本概念 在 Unity 中,协程是一种轻量级的任务执行机制,允许脚本中的方法暂停并稍后继续运行协程通过 `IEnumerator` 接口定义,并由 `StartCoroutine` 方法启动[^4]。Unity 协程的核心特点是基于帧驱动的工作方式,这意味着每次更新都依赖于游戏循环的时间间隔。 以下是创建和管理协程的一个简单示例: ```csharp using UnityEngine; public class Example : MonoBehaviour { IEnumerator MoveObject() { while (true) { transform.position += Vector3.forward * Time.deltaTime; yield return null; // 每帧暂停一次 } } void Start() { StartCoroutine(MoveObject()); } } ``` #### 2. 线程 (Thread) 的基本概念 线程是由操作系统支持的一种更底层的并发控制单元。C# 提供了 `System.Threading.Thread` 类用于操作多线程程序。相比协程,线程具有独立的内存空间和 CPU 时间片分配能力,能够真正实现跨多个核心的同时计算[^1]。 以下是一个简单的线程示例: ```csharp using System.Threading; using UnityEngine; public class ThreadExample : MonoBehaviour { private bool isRunning = true; void Start() { new Thread(() => { while (isRunning) { Debug.Log("This runs on a separate thread."); Thread.Sleep(1000); // 让线程休眠一秒 } }).Start(); } void OnDestroy() { isRunning = false; // 停止线程 } } ``` #### 3. 使用场景对比 ##### **协程** - 主要适用于需要按时间分段完成的操作,例如动画播放、延迟加载资源或逐步改变某个属性。 - 不适合涉及复杂逻辑或长时间阻塞的操作,因为这些可能会影响主线程性能。 - 受限于单一线程环境,无法利用现代硬件的多核优势[^2]。 ##### **线程** - 更加灵活,可用来处理耗时任务(如文件读写、网络通信),而不会阻碍 UI 或其他实时交互功能。 - 需要注意同步问题以及访问共享数据的安全性,这增加了开发难度。 - 如果频繁切换上下文,则可能导致额外开销甚至降低整体效率[^1]。 #### 4. 差异总结 | 属性 | 协程 | 线程 | |--------------|-------------------------------|------------------------------| | 执行模型 | 同步模拟 | 异步真实 | | 资源消耗 | 较低 | 相对较高 | | 并发级别 | 单线程内的伪并发 | 多线程间的真并发 | | 数据安全性 | 自然隔离 | 易受竞态条件影响 | 尽管两者都能解决某些类型的编程挑战,但在实际应用过程中需权衡各自的优缺点以选取最合适的解决方案。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值