有什么不明白的地方,扫描右方二维码加我微信交流。
       

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

 

这样我们就实现了一个简单的数字变化协程。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注