unity3d - 为什么 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,我很抱歉它的质量很差,但希望你能看到问题。
解决方案
绝对不是WaitForSeconds
改变精灵而是你的Animator
!
原因
如果在任何 s 中的某个地方,您对于某个属性AnimatorState
只有一个关键帧Sprite
(就像在您的情况下显然是),则Animator
可以完全控制该属性,并且您不能再通过脚本覆盖它了!
此外,AnimatorState
还有一个Write Defaults
UnityTechnologies 在此线程中所说的选项
在 5.0 中,我们在 State 上添加了一个属性到
Write back default values
. 这意味着如果打开,它将写回在该状态下没有动画的所有动画属性的默认值(在控制器范围内) 。默认情况下,它是“开启”的,所以我们不会改变我们之前的行为。
因此,如果您希望 State 的非动画属性保持其先前的值,只需将其关闭即可。
这意味着对于此 AnimatorState 中没有关键帧的每个属性,它使用对象将具有的默认值(如果没有关键帧) Animator
。
一种解决方案
因此,如果您希望您的Default
状态不覆盖,Sprite
因为Sprite
在该状态下没有关键帧,那么只需打开此选项。
纯动画师解决方案
但是,我认为你可以设置你的 Animator,它实际上可以处理整个事情,而不需要你的脚本,除了启动动画一次。
你说你的 Animator 设置看起来像
进入→默认←解锁
所以请允许我问:
为什么不简单地删除转换回
Default
?这将使它保持在unlock
状态,直到你告诉它。通过Loop Time
像您已经拥有的那样打开,这意味着它会停留在最后一个关键帧,并且无论如何都不会跳回默认值。为什么不简单地将淡出也包含在您的
unlock
动画中呢?只需为color
属性设置关键帧。这样您就不需要为此使用脚本。或者,如果您想独立于(解锁)锁定来控制淡入淡出,您可以使用多个动画层!在主层上,您进行(解锁)锁定。在不同的图层上,您通过
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
更改。然后,您仍然可以通过脚本控制它,但不必“手动”等到解锁动画完成后再开始淡出。
我知道这是很多信息,但我希望这个想法变得清晰,您可以通过文档了解自己的方式;)
推荐阅读
- python - 打印 numpy 矩阵的每一行和每一列索引及其值
- grafana - 如何在 Grafana 中显示结果表
- css - 如何在 docsify 中使侧边栏更宽?
- node.js - NodeJS 中的文件操作是使用 OS 异步(轮询?)还是阻塞事件循环?
- r - 检查 GLMM 的线性假设
- ssis - 如何替换“?” 在 SSIS 表达式中使用 NULL?
- embedded - 未解析的符号 pthread_create,首先在 ./armrtk/src/task.obj 中引用
- google-analytics - 有没有办法从自定义搜索页面整合事件操作?
- xcode - Xcode (12.3) 连接到 Internet 时没有响应?
- mysql - 如何防止 Google 表格和日历之间的 Apps 脚本中的双重预订