【问题标题】:Transform position not updated immediately变换位置未立即更新
【发布时间】:2018-10-20 11:27:01
【问题描述】:

我制作了一个动画事件,一旦动画完成,它会更新变换位置,然后调用一个方法来检查玩家是否降落在特定的图块上。

但是,变换位置并未立即更新。我写了一个协程等待一小段时间。

一个简单的案例:

public void OnAnimationFinish() {
    transform.position = landOn;
    Debug.Log("Start from: " + landOn);

    JumpIfOnTile();
}

private void JumpIfOnTile() {
    // not same if you don't wait
    Debug.Log("Start from: " + transform.position);
}

解决方法:

private IEnumerator JumpIfOnTile() {
    yield return new WaitForSeconds(.5f);
    // then everything ok
    Debug.Log("Start from: " + transform.position);
}

【问题讨论】:

  • 您确定JumpIfonTile 不是从其他地方调用的吗?这似乎是不可能的,尤其是如果OnAnimationFinish 中的第一个Log 显示更新后的transform.position。你能在OnAnimationFinish 中设置一个断点并测试到底发生了什么吗?
  • @MartinZikmund 似乎将位置设置为landOn 实际上并未更新位置。
  • 第一个Log 是否输出landOn 位置?
  • @MartinZikmund 实际上我打印了landOn。我编辑了帖子。
  • 动画是否也在修改位置?如果动画实际上还没有完全完成,它可能不会让你更新它

标签: c# unity3d


【解决方案1】:

我在最后一帧上钩了 OnAnimationFinish。理论上 动画应该完成。

看起来动画并没有真正完成,并且正在覆盖您为对象设置的位置。与其等待很长的.5f 秒,不如在动画可能完成时等待帧结束,这是通过yield return new WaitForEndOfFrame() 完成的。如果仍有问题,请等待带有yield return null 的帧。

虽然这应该可以解决您的问题,但我不建议您使用内置动画事件来检测动画结束,只需通过代码执行即可。请参阅我的另一个 post 中的 PlayAndWaitForAnim 函数,它显示了如何播放动画然后等待它完成播放。将您的转换移动到 PlayAndWaitForAnim 函数的末尾。

编辑:

为什么我必须等待一帧?

记得我说过你可以用WaitForEndOfFrame 等到帧结束或等待帧。 Unity 正在更新每一帧的动画。由于您将事件设置为最后一帧,因此您无法保证何时调用事件(在最后一帧之前或之后)。如果在帧之前调用事件并且您设置了位置,则动画将在帧结束时覆盖它。这就是为什么您要等到帧结束或仅一帧才能保证动画不再动画的原因。观看 this 视频以更深入地了解正在发生的事情。

为什么你更喜欢脚本而不是内置动画事件?是吗 偶尔表现出意外?

我更喜欢为此编写脚本,因为它可以避免与您问题中的问题一样的问题。动画事件文档上应该有一条警告说“不要使用这个”。动画事件可能会导致您的游戏出现缓慢的错误,并且此问题随机发生。我不确定这是否已修复。它可以做的最糟糕的事情是根本不被调用,当您的动画由于低帧速率而错误地跳过一帧时,就会发生这种情况。他们声称他们已经解决了这个问题,但它是not true。回调函数不被调用会彻底破坏你的游戏。

如果您需要动画的回调类型事件,请在我链接的PlayAndWaitForAnim 函数中实现event and delegate。不要使用 Unity 的动画事件。

【讨论】:

  • 感谢您的回复。它可能与这个问题没有直接关系,但你能解释更多关于 1. 为什么我必须等待一个框架?我假设事件系统在每一帧上轮询,并处理来自动画、脚本等的异步调用; 2. 为什么你更喜欢脚本而不是内置动画事件?它是否偶尔会出现意外行为?我问是因为我没有在官方网站上看到“最佳实践”。我也没有阅读有关动画事件的完整解释。
【解决方案2】:

尝试在JumpIfOnTile(); 执行之前设置一个条件。例如

public void OnAnimationFinish() {
    transform.position = landOn;
    Debug.Log("Start from: " + transform.position);

    if(transform.position == landOn)
    JumpIfOnTile();
}

【讨论】:

  • 我编辑了这篇文章。在您的情况下,条件失败。
猜你喜欢
  • 2015-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多