【问题标题】:Infinite Loop Crashing, but not in Update Function无限循环崩溃,但不在更新函数中
【发布时间】:2018-05-17 16:51:14
【问题描述】:

这些脚本会导致 Unity 挂起。我在这里错过了什么?

考虑到 Unity 如何处理循环,我知道这可能是有史以来最愚蠢的问题。但我发誓我以前写过这个并且成功了......我做错了什么?我得到循环是无限的,但它必须不断迭代。

定时器.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Timer{
    float tickTime;
    float lastTicktime;
    bool timerRunning = false;

    public Timer (float tickTime) {
        this.tickTime = tickTime;
    }

    public void StartTimer() {
        timerRunning = true;
        lastTicktime = Time.time;
        GenerateTicks ();

    }

    public void StopTimer () {
        timerRunning = false;
    }

    void GenerateTicks () {
        while (timerRunning) {
            if ((Time.time - lastTicktime) > tickTime) {
                Debug.Log ("Tick");
                lastTicktime = Time.time;
            }
        }
    }
}

实施

Timer timer;
    void Start () {
        timer = new Timer (triggerTime);
        timer.StartTimer ();
}

【问题讨论】:

  • 不完全确定你在问什么 - 但看起来你从来没有打电话给 StopTimer() 将 timerRunning 设置为 false 所以它卡在 while 循环中
  • 您的timerRunning 始终是true
  • 它是否特别需要成为一个循环?为什么不能在 Update() 中只运行一次?

标签: loops unity3d time while-loop timer


【解决方案1】:

代码永远不会退出while(timerRunning) 循环,因为您永远不会在所述循环内执行timerRunning = false

此外,即使您在 if ((Time.time - lastTicktime) > tickTime) { } 部分中添加 timerRunning = false,您也会暂停 Unity 主线程的执行,直到该条件为 true(基本上,Unity 至少会停止到 tickTime 秒已经过去了)。

如果您需要使用计时器并让 Unity 执行,则使用协程。

编辑:要回答您的评论,请像这样修改您的代码:

using UnityEngine;
using System.Collections;

public class Timer {

    float tickTime;
    float lastTicktime;
    bool timerRunning = false;

    public Timer(float tickTime) {
        this.tickTime = tickTime;
    }

    public IEnumerator StartTimer() {
        timerRunning = true;
        lastTicktime = Time.time;
        while (timerRunning) {
            if ((Time.time - lastTicktime) > tickTime) {
                Debug.Log("Tick");
                lastTicktime = Time.time;
                timerRunning = false;
            }
            yield return null;
        }
    }
}

实施:

private Timer timer;
private IEnumerator timerCoroutine;

private void Start() {      
    timer = new Timer(triggerTime);
    timerCoroutine = timer.StartTimer();
    StartCoroutine(timerCoroutine);
}

【讨论】:

  • 非常感谢,但是如果计时器类没有从单一行为扩展,我该如何启动协程?我可以创建 ienumerators 但 StartCoroutine 无处可寻。我可以从实现类中调用它吗?我已经尝试过了,但收效甚微。
  • 我编辑了我的答案,向您展示如何使用来自另一个非 Monobehaviour 类的协程。基本上,要将一个方法作为协程启动,您只需要它返回一个IEnumerator,就可以了。
猜你喜欢
  • 2014-01-31
  • 1970-01-01
  • 2016-06-19
  • 1970-01-01
  • 2023-01-31
  • 1970-01-01
  • 2020-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多