首页 > 解决方案 > 为什么 WaitForSeconds 会导致我的精灵被更改?

问题描述

在我的游戏中,我播放动画,等待动画结束,然后更改精灵图像。接下来我淡出精灵,等待淡入淡出结束,然后禁用游戏对象。这是代码:

IEnumerator UnlockSequence()
{
    anim.Play("unlock");
    unlocking = false; // stops UnlockSequence from being called again
    yield return new WaitForSeconds(1.7f);

    sr.sprite = sprite1; //change sprite

    StartCoroutine(FadeTo(0.0f, 2.0f)); 
    yield return new WaitForSeconds(2f);

    gameObject.SetActive(false);
}

IEnumerator FadeTo(float aValue, float aTime)
{
    float alpha = sr.color.a;
    for (float t = 0.0f; t < 1.0f; t += Time.deltaTime / aTime)
    {
        Color newColor = new Color(sr.color.r, sr.color.g, sr.color.b, Mathf.Lerp(alpha, aValue, t));
        sr.color = newColor;
        yield return null;
    }
}

这很好用,除非当我看到yield return new WaitForSeconds(2f);精灵图像回到动画之前的原始图像时。我不知道为什么会这样。我知道这很sr.sprite = sprite1;有效,因为当我取出精灵时yield return new WaitForSeconds(2f);,精灵是正确的。任何解决此问题的帮助将不胜感激。

编辑:

这是问题的 GIF,我很抱歉它的质量很差,但希望你能看到问题。

问题

标签: unity3dsprite

解决方案


绝对不是WaitForSeconds改变精灵而是你的Animator

原因

如果在任何 s 中的某个地方,您对于某个属性AnimatorState只有一个关键帧Sprite(就像在您的情况下显然是),则Animator可以完全控制该属性,并且您不能再通过脚本覆盖它了!

此外,AnimatorState还有一个Write DefaultsUnityTechnologies 在此线程中所说的选项

在 5.0 中,我们在 State 上添加了一个属性到Write back default values. 这意味着如果打开,它将写回在该状态下没有动画的所有动画属性的默认值(在控制器范围内) 。

默认情况下,它是“开启”的,所以我们不会改变我们之前的行为。

因此,如果您希望 State 的非动画属性保持其先前的值,只需将其关闭即可。

这意味着对于此 AnimatorState 中没有关键帧的每个属性,它使用对象将具有的默认值(如果没有关键帧) Animator

一种解决方案

因此,如果您希望您的Default状态不覆盖,Sprite因为Sprite在该状态下没有关键帧,那么只需打开此选项。


纯动画师解决方案

但是,我认为你可以设置你的 Animator,它实际上可以处理整个事情,而不需要你的脚本,除了启动动画一次。

你说你的 Animator 设置看起来像

进入→默认←解锁

所以请允许我问:

  1. 为什么不简单地删除转换回Default?这将使它保持在unlock状态,直到你告诉它。通过Loop Time像您已经拥有的那样打开,这意味着它会停留在最后一个关键帧,并且无论如何都不会跳回默认值。

  2. 为什么不简单地将淡出也包含在您的unlock动画中呢?只需为color属性设置关键帧。这样您就不需要为此使用脚本。

  3. 或者,如果您想独立于(解锁)锁定来控制淡入淡出,您可以使用多个动画层!在主层上,您进行(解锁)锁定。在不同的图层上,您通过Color属性进行淡化。

一般来说,我通常会建议使用bool 动画参数进行动画设置。然后使用多层它可能看起来像

parameters 
   Bool "Open"
   Bool "FadeOut"

layers
    Base Layer

    Entry       -------------------> StateClosed
    StateClosed --(if Open==true)--> AnimOpening
    AnimOpening --(Exit time 1)----> StateOpen
    StateOpen   --(if Open==false)-> AnimClosing
    AnimClosing --(Exit time 1)----> StateClosed

    FadeingLayer (make sure to set Weight to `1` -  its `0` by default)

    Entry          -----------------------> StateFadedIn
    StateFadedIn   --(if FadeOut==true)---> AnimFadingOut
    AnimFaidingOut --(Exit time 1)--------> StateFadedOut
    StateFadedOut  --(if FadeOut==false)--> AnimFadingIn
    AnimFadingIn   --(Exit time 1)--------> StateFadedIn

如果您想确保为所有状态中的所有相应属性设置关键帧,包括单个关键帧状态。含义例如在您设置的 FadingLayer 中

StateFadedIn: Color.a = 1
StateFadedOut: Color.a = 0
AnimFadingOut: Color.a = well your keyframes here ;)
AnimFadingIn: Color.a = well your keyframes here ;)

和 BaseLayer 一样。

这样Animator,当通过脚本强制在状态之间跳转时,就不会搞砸了。

然后在代码中简单地设置

anim.SetBool("Open", true);

进而

anim.SetBool("FadeOut", true);

最后,您可以通过设置动画事件而不是最后一次脚本调用来增强它,从而在完成时自动调用FadeOut更改。然后,您仍然可以通过脚本控制它,但不必“手动”等到解锁动画完成后再开始淡出。


我知道这是很多信息,但我希望这个想法变得清晰,您可以通过文档了解自己的方式;)


推荐阅读