我正在开发一些飞行模拟器程序。现在我试图在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 :(得分:4)
通常,当WaitForSeconds不起作用时,它是两件事之一:
在你的情况下,在调用yield WaitForSeconds之前,你正在销毁运行Coroutine的游戏对象。 Destroy被推迟到帧结束,所以代码一直到yield将执行,然后GameObject& MonoBehaviour将被摧毁,Coroutine也将被摧毁。
解决方案:对在结束和重新启动之间持续存在的对象使用Coroutine。要使对象在加载关卡时保持不变(正如您在代码中所做的那样),您需要调用DontDestroyOnLoad。
答案 1 :(得分: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");
}
答案 2 :(得分:2)
我仍然不明白为什么人们仍然会考虑在简单的情况下使用co例程。我建议只使用co例程,就好像你在服务器上检查一些东西一样。与其他函数进行常规调用。
但是当你只想“等待”< - 这是关键词时,请不要使用常规通话。等待该功能不合作。
如果您的目标是使用Application.Load重新启动游戏,请使用此功能。
public void MyRestart(){
Application.LoadLevel("MyLevel");
// Put your codes where ever in this method.
}
然后只使用Invoke Method
Invoke ("MyRestart", 4);
//这将在4秒后调用MyRestart函数。
答案 3 :(得分:0)
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");
}
我没有测试过,我希望它有效