在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;
}
这样我们就实现了一个简单的数字变化协程。