首页 > 解决方案 > Unity5:有没有什么想法在没有协程的情况下编写代码淡入/淡出?

问题描述

我正在考虑通过 C# 制作 FadeIn/Out 效果。

// 所以,如果有这样的代码:

    float targetAlpha = 0.7f;
    Color targetColor = new Color();

    public void FadeIn() {
    if(color.a < targetAlpha) { color.a += Time.deltaTime; }
    sprite.color = targetColor;
    }

1)我不想把 FadeIn() 放在 Update() 中,因为我不经常使用这个 FadeIn() 函数。

2)我不想使用协程,因为 StartCoroutine() 会产生垃圾。我会经常打开/关闭这个对象。

3) 动画师……没办法吧?

所以我要做1个事件,它总是在Update()上起作用,然后我会把所有的东西都放在那个事件里。(在 OnEnable() 时添加,在 OnDisable() 时移除)

有更好的解决方案吗?

标签: c#unity3doptimization

解决方案


如果您不想将其放入更新中,因为它不会经常使用,也许您可​​以考虑使用状态机方法。如果性能确实比可读性更重要,我只会考虑这一点。因为这种方式会增加很多额外的代码。

为简单起见,下面的代码比它必须的更冗长。

public interface IState
{
    void Update();
}

public class FadeInState : IState
{
    private readonly float targetAlpha;
    private readonly Sprite sprite;
    private readonly Action onComplete;

    public FadeInState(Sprite sprite, float targetAlpha, Action onComplete)
    {
        this.targetAlpha = targetAlpha;
        this.sprite = sprite;
        this.onComplete = onComplete;
    }

    public void Update()
    {
        // Your fade-in code
        if (sprite.color.a < targetAlpha)
        {
            Color tmp = sprite.color;
            tmp.a += Time.deltaTime;
            sprite.color = tmp;
        }
        else
        {
            this.onComplete.Invoke();
        }
    }
}

public class FadeOutState : IState
{
    private readonly float targetAlpha;
    private readonly Sprite sprite;
    private readonly Action onComplete;

    public FadeOutState(Sprite sprite, float targetAlpha, Action onComplete)
    {
        this.targetAlpha = targetAlpha;
        this.sprite = sprite;
        this.onComplete = onComplete;
    }

    public void Update()
    {
        // Your fade-out code
        if (sprite.color.a > targetAlpha)
        {
            Color tmp = sprite.color;
            tmp.a -= Time.deltaTime;
            sprite.color = tmp;
        }
        else
        {
            this.onComplete.Invoke();
        }
    }
}

public class DoNothingState : IState
{
    public void Update()
    {
        // Do nothing
    }
}

public class YourClass : MonoBehaviour
{
    private IState currentState;

    void Awake()
    {
        this.currentState = new DoNothingState();
    }

    void Update()
    {
        this.currentState.Update();
    }

    public void FadeIn(Sprite sprite, float targetAlpha)
    {
        this.currentState = new FadeInState(sprite, targetAlpha,
            () =>
            {
                this.currentState = new DoNothingState();
            });
    }

    public void FadeOut(Sprite sprite, float targetAlpha)
    {
        this.currentState = new FadeOutState(sprite, targetAlpha,
            () =>
            {
                this.currentState = new DoNothingState();
            });
    }
}

最初,您的班级处于该DoNothing州。所以更新实际上什么都不做。

如果有人打电话FadeIn,你FadeInState会做你的衰落逻辑,就好像它在MonoBehaviour.Update().

状态在完成时执行的构造函数中接受一个动作。通过这种方式,您可以从内部控制动画完成后发生的情况YourClass。在示例中,我只是将状态设置为,DoNothing但您可能可以禁用游戏对象。

如果您采用这种方法并开始将其用于其他事情,您应该研究一些更好的 StateMachine 实现。否则你最终会得到大量的状态类。这个不错


推荐阅读