无法神秘地跟踪正在改变变量的内容

时间:2016-02-21 14:00:05

标签: c# unity3d

我有一个带有网格布局的面板,我将实例化的预制文本对象克隆。

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

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

Screenshot from live version of the prototype

当按下我的按钮时,我从新计时器调用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);
    ...
}

ResearchTimer脚本类StartTimer(float)所在的位置,我遇到了我试图找到的问题:

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未在代码中的任何其他位置设置。为什么会这样?

另一方面,我了解到我似乎并不需要这个变量,但我仍然很好奇它为什么会发生。

1 个答案:

答案 0 :(得分:1)

ResearchTimer课程中,将isStarted = false放入Awake方法。

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

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

如果您在isStarted而不是Awake中初始化Start,则应在实例化newTimerObject之后立即调用它,并在调用`StartTime&#39;之前调用void Awake () { visualText = GetComponent<Text> (); //I initiate it to false here because //I don't need updates before the timer starts. isStarted = false; }

Awake

这是从内存开始的,因此可以在您的实例中进行确认。但是,以下链接说明了何时调用Start _ _ _ _ _ | | | | 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...

Unity - Execution Order of Event Functions

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

Start

您可以使用此功能,因为Start仅在您自己的代码&#34; 之后运行&#34;你不知道你的代码运行的顺序是什么,但是,你知道Start总是运行&#34;在所有代码之后,无处不在&#34;。假设您正在制造宇宙飞船,敌舰和货船。 String singleBookItem = getItem(position); String singleBookSubject = getItem(position); 运行后,您知道所有三个都在那里。