【问题标题】:Unity - WaitForSeconds() does not workUnity - WaitForSeconds() 不起作用
【发布时间】:2015-04-10 02:16:00
【问题描述】:

我正在开发一些飞行模拟器程序。现在我正试图让关卡在延迟 4 秒后重新启动,但它一直在等待并且没有响应。这是我现在的代码(在 C# 中):

void Update () {

    //other irrelevant code in front

    float TerrainHeightLocation = Terrain.activeTerrain.SampleHeight (transform.position);

    if (TerrainHeightLocation > transform.position.y) { //the plane crashed

        StartCoroutine(Wait(TerrainHeightLocation));


    }
}

IEnumerator Wait( float TerrainHeightLocation) {
    transform.position = new Vector3 (transform.position.x,
                                      TerrainHeightLocation,
                                      transform.position.z);
    Instantiate(explosion, transform.position, transform.rotation);
    Destroy(gameObject);

    Debug.Log ("Waiting");
    yield return new WaitForSeconds(4.0f); // waits x seconds

    Debug.Log ("Waited for x seconds");

    Application.LoadLevel(Application.loadedLevel);
    Debug.Log ("Reloaded level");

}

如果有人能在代码中找到问题,那将是一个很大的帮助,因为我已经尝试了一整天,但我无法修复它。

谢谢!

【问题讨论】:

  • 什么实际上不起作用?你在等待函数中确实有一个零,所以不会有任何延迟
  • 是的,但程序没有等待 0.0f 秒。出于某种原因,它会永远等待。
  • 它会永远等待任何值吗?
  • 是的,很不幸
  • 当你注释掉那个等待函数调用时会发生什么?

标签: c# unity3d


【解决方案1】:

通常,当 WaitForSeconds 不起作用时,它是以下两种情况之一:

  1. Time.timeScale 设置为 0。
  2. 对象正在被销毁或在时间结束之前处于非活动状态。

在您的情况下,您正在销毁运行 Coroutine 的游戏对象,然后再调用 yield WaitForSeconds。 Destroy 被推迟到帧结束,所以直到 yield 的代码才会执行​​,但是 GameObject 和 MonoBehaviour 将被销毁,Coroutine 也会随之被销毁。

解决方案:在关卡结束和重启之间持续存在的对象上使用协程。要使对象即使在加载关卡时仍然存在(正如您在代码中所做的那样),您需要调用 DontDestroyOnLoad。

【讨论】:

    【解决方案2】:

    您的代码的问题是您正在破坏调用此协程的游戏对象。所以当你在你的游戏对象上调用destroy时,它将停止运行协程(至少应该在这里发生)。这个问题的解决方案不是破坏游戏对象,而是始终禁用它的渲染器和碰撞器。然后在加载新关卡时重新启用它们。所以你不需要销毁对象。

    就您的场景而言,它看起来像是已预定义的。如果您的场景已从默认值初始化对象,则只需隐藏需要销毁的对象即可。我认为这应该可以解决您的问题。加载级别将销毁场景中的所有对象并重新加载它们。

         IEnumerator Wait( float TerrainHeightLocation) {
            transform.position = new Vector3 (transform.position.x,
                                              TerrainHeightLocation,
                                              transform.position.z);
            Instantiate(explosion, transform.position, transform.rotation);
            //Hide the game object renderer and colliders here instead of destroying it
            //as this is the script which controls your coroutine execution.
            gameObject.renderer.enabled = false;
            gameObject.collider.enabled = false;
    
            //Make sure your game object has required renderer and collider or else the           
            //above code will give errors as it wont be able to find them
    
            Debug.Log ("Waiting");
            yield return new WaitForSeconds(4.0f); // waits x seconds
    
            Debug.Log ("Waited for x seconds");
    
            Application.LoadLevel(Application.loadedLevel);
            Debug.Log ("Reloaded level");
    
        }
    

    Similer Question

    【讨论】:

      【解决方案3】:

      我仍然不明白为什么人们仍然会考虑在简单的情况下使用协程。我建议只使用 co 例程,就好像您正在检查服务器上的某些内容一样。与其他函数进行协程调用。

      但是当你只想“等待”

      如果您的目标是使用 Application.Load 重新启动游戏,请使用它。

      public void MyRestart(){
      
         Application.LoadLevel("MyLevel");
         // Put your codes where ever in this method.
      }
      

      那就用调用方法

      Invoke ("MyRestart", 4);
      

      //这将在 4 秒后调用 MyRestart 函数。

      【讨论】:

        【解决方案4】:
        bool isDead = false;
        
        void Update () //Update calls your function every frame. So we should call IEnumerator for one time. I will use bool check for this.
        {
        
            //other irrelevant code in front
        
            float TerrainHeightLocation = Terrain.activeTerrain.SampleHeight (transform.position);
        
            if ( (TerrainHeightLocation > transform.position.y) && !isDead ) { //the plane crashed
        
                isDead = true;
                InstantiateFunc( TerrainHeightLocation );
                StartCoroutine(Death);        
        
        
            }
        }
        
        void InstantiateFunc( float TerrainHeightLocation) {
            transform.position = new Vector3 (transform.position.x,
                                              TerrainHeightLocation,
                                              transform.position.z);
            Instantiate(explosion, transform.position, transform.rotation);
            Destroy(gameObject);
        
            Debug.Log ("Waiting");
        
        }
        
        IEnumerator Death{
        yield return new WaitForSeconds(4.0f); // waits x seconds
        
                Debug.Log ("Waited for x seconds");
        
                Application.LoadLevel(Application.loadedLevel);
                Debug.Log ("Reloaded level");
        }
        

        我没有测试过,我希望它有效

        【讨论】:

        • 函数旁边缺少一些括号,但不,它不起作用。
        猜你喜欢
        • 2015-06-14
        • 2015-12-20
        • 1970-01-01
        • 2019-10-27
        • 1970-01-01
        • 1970-01-01
        • 2022-10-05
        • 2015-03-02
        • 1970-01-01
        相关资源
        最近更新 更多