在Unity中使用自定义协程CustomCoroutine
有什么不明白的地方,扫描右方二维码加我微信交流。
IfeelgameFramework里有一个Toast模块,Toast展示2s后执行一个淡出动画。
- 为了减少Toast的复杂性,没有使用Unity的Animation系统;
- 为了保持IfeelgameFramework独立性,未引入DOTween模块。
于是想到用协程来实现Toast的淡出。
分析
先看Unity里的协程
void Start() { StartCoroutine(DelaySeconds()); } private IEnumerator DelaySeconds() { yield return new WaitForSeconds(0.5f); //do something }
调用StartCoroutine
,传入参数DelaySeconds()
,DelaySeconds
返回IEnumerator
类型的值,所以实现一个自定义协程,本质上就是要实现一个IEnumerator
。我们看下IEnumerator
的代码,如下:
namespace System.Collections { public interface IEnumerator { object Current { get; } bool MoveNext(); void Reset(); } }
IEnumerator是一个迭代器,实现自定义协程,就是要实现一个自定义的迭代器。
将迭代器传入StartCoroutine
方法中,Unity每帧都会调用MoveNext
,这部份Unity已经在内部帮我们处理好了,所以我们要做的就是实现MoveNext
的部分。
实现方案
淡出动画本质上就是opacity参数从1到0的过程。所以我们实现一个迭代器,使其可以在固定的帧数内从1平均数到0。
实现代码如下:
using System; using System.Collections; public class CoroutineNumChange : IEnumerator { private readonly float _numStart; private readonly float _numEnd; private float _numCurrent; private readonly float _numOffset; private readonly Action<float> _moveNextCallback; /// <summary> /// 构造函数 /// </summary> /// <param name="numStart">开始数字</param> /// <param name="numEnd">结束数字</param> /// <param name="frameCount">所需帧数</param> /// <param name="moveNextCallback">每帧变化完成后的回调</param> public CoroutineNumChange(float numStart, float numEnd, int frameCount, Action<float> moveNextCallback) { _numStart = numStart; _numEnd = numEnd; _moveNextCallback = moveNextCallback; _numCurrent = _numStart; _numOffset = (_numEnd - _numStart) / frameCount; } public bool MoveNext() { _numCurrent += _numOffset; if (Math.Abs(_numCurrent - _numStart) >= Math.Abs(_numEnd - _numStart)) { _numCurrent = _numEnd; } _moveNextCallback?.Invoke(_numCurrent); return Math.Abs(_numCurrent - _numStart) < Math.Abs(_numEnd - _numStart); } public void Reset() { _numCurrent = _numStart; } public object Current => _numCurrent; }
在Unity中的调用代码如下:
void Start() { StartCoroutine(FadeOut()); } private IEnumerator FadeOut() { var cor = new CoroutineNumChange(1, 0, 60, opacity => { GetComponent<CanvasGroup>().alpha = opacity; }); yield return cor; }
这样我们就实现了一个简单的数字变化协程。