【问题标题】:Can't track what is changing a variable mysteriously无法跟踪是什么神秘地改变了变量
【发布时间】:2016-07-15 00:58:23
【问题描述】:

我有一个带有网格布局的面板,我在其中放置了预制文本对象的实例化克隆。

可视计时器表示的每个实例都有一个附加的计时器脚本。

还有一个将这些文本对象添加到列表(面板)的按钮:

当我的按钮被按下时,我从新计时器中调用StartTimer 函数(我省略了所有用于实例化研究名称文本的类似代码):

public void AddResearch() {
    ...
    float timeInSeconds = (float) Random.Range(5, 16);
    ...
    GameObject newTimerObject = (GameObject) Instantiate(
        researchTimerPrefab,
        researchList.transform.position,
        researchList.transform.rotation);
    newTimerObject.transform.SetParent(researchList.transform);
    ...
    newTimerObject.GetComponent<ResearchTimer> ().StartTimer (timeInSeconds);
    ...
}

StartTimer(float) 所在的ResearchTimer 脚本类中,我遇到了我要查找的问题:

public class ResearchTimer : MonoBehaviour {

    public float timeRemaining;

    private Text visualText;
    private bool isStarted; //This is the variable I don't understand

    void Start () {
        visualText = GetComponent<Text> ();
        //I initiate it to false here because
        //I don't want update called before the timer starts.
        isStarted = false;
    }

    void Update () {
        //Here, isStarted is always false after setting it to true "StartTimer"
        if (!isStarted) return;

        //code to update text representation of the timer
        ... 
    }

    public void StartTimer(float timeInSeconds) {
        timeRemaining = timeInSeconds;
        isStarted = true;

        //When I set a breakpoint here, the "isStarted" variable is changed to true,
        //but the next time the Update function runs, it's false again.
        //That is the part I don't understand

        InvokeRepeating ("decreaseTimeRemaining", 1.0f, 1.0f);
    }

    void decreaseTimeRemaining()
    {
        //If I set isStarted here, it shows correctly (as per screenshot),
        //but then it won't be set before the first second has passed
        isStarted = true;
        timeRemaining--;
    }

    ...
}

isStarted 未在代码中的其他任何位置设置。为什么会这样?


顺便说一句,我知道我似乎不需要这个变量,但我仍然很好奇它为什么会发生。

【问题讨论】:

  • 您知道 isStarted 默认以false 开头吗?你问的是这个吗?
  • 我真正要问的是为什么在调用StartTimer() 之后isStarted 仍然是假的。我知道Start() 在我调用StartTimer() 之前就被调用了,所以我不明白为什么/如何在此之后再次将其设置为false。这有帮助吗?
  • 好点。这是我的错误,也是一个非常尴尬的错误。我一定很困惑。对不起。
  • 这类问题很容易解决。确保您包含 >>>>所有
  • 我不知道你为什么在这里向 cmets 发送垃圾邮件。我知道如何使用Debug.Log()。正如您所指出的, isStarted 是一个私有变量,那么为什么其他文件很重要?这是every mention of isStarted,我已经在上面的问题中向您展示过。讨论 +++=1v = v+1 似乎都与讨论无关。请在别处讨论。

标签: c# unity3d


【解决方案1】:

在您的ResearchTimer 类中,将isStarted = false 放在Awake 方法中。

当您的newTimerObject 被实例化时,该对象上每个组件的Awake 方法都会被调用,但在第一次更新执行之前不会调用Start

因此,在您的情况下,调用 Awake 方法(如果有的话),然后调用 StartTimerisStarted 设置为 true,但是当执行下一次更新时,Start 方法被调用,然后将其设置为false

如果您在Awake 中初始化isStarted,而不是Start,那么它应该在newTimerObject 被实例化之后并且在您调用“StartTime”之前调用。

void Awake () {
    visualText = GetComponent<Text> ();
    //I initiate it to false here because
    //I don't need updates before the timer starts.
    isStarted = false;
}

这是根据记忆进行的,因此可以在您的实例中确认这一点。但是,以下链接解释了何时调用 AwakeStart

Unity - Execution Order of Event Functions

这是一个帧中发生的事情的 ascii-art 图。

 _ _ _ _ _
|
|
|
|  all your various code runs here
|  you instantiate something .. Awake runs
|  all your various code runs here
|  you instantiate something .. Awake runs
|  you instantiate something .. Awake runs
|  all your various code runs here
|
|  unity does many things here, drawing, physics, etc etc
|  unity does many things here, drawing, physics, etc etc
|  unity does many things here, drawing, physics, etc etc
|
|_ _ _ _ _ _ 
|  all of the Starts are run at once here
|_ _ _ _ _ 
|
| next frame begins...

您可以利用它来发挥自己的优势,因为 Start 仅在 “在所有您自己的代码之后” 运行。你不知道你的代码运行的顺序是什么,但是,你知道Start 总是“在所有你的代码之后,无处不在”运行。假设你正在制造一艘宇宙飞船、一艘敌舰和一艘货船。一旦Start 运行,您就知道所有三个都在那里。

【讨论】:

  • 完全正确。 正如我向 OP 提到的,如果他们只是添加一个 Debug 行,就会清楚地看到“isStarted = false”是在 之后调用的 调用 StartTimer。
  • 确实,正如有人在第一条评论中提到的那样,“你知道isStarted 将默认以false 开头吗?”不费心将其“重新初始化”为默认值可能更合理。但无论如何,MotoSV 已经完全解释了这个问题。重要的是要知道 Awake 在对象实例化时运行,但 Start 仅在“runloop 启动时”运行(稍后)。
  • 这正是我在问题中包含第一段的原因,@JoeBlow 将其删除。我认为这可能与事件生命周期有关。我想我应该先解释一下我是如何看待事件循环的,以便有人更容易纠正我。老实说,我仍然不完全理解它,而且我现在无法对其进行测试,因为我遇到了另一个错误,导致我目前无法运行该程序。我认为这是因为我重命名了预制件,从而破坏了一些元数据。我会恢复到上次保存的时间,并在我可以测试时通知您。
  • 你可以随时恢复编辑,我删除了这个我希望我知道如何更具体,但我很有信心我的问题来自对某些结构部件工作缺乏了解在 Unity 中。
  • JoeBlow:请不要修改已被接受的答案。如果您认为答案不正确或可以改进,请发布您自己的解决方案,如果这被认为是更准确的答案,那么 Aske B 可以选择接受此答案。
猜你喜欢
  • 2013-02-20
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
  • 1970-01-01
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多