c# - 无法跟踪什么正在神秘地改变变量

标签 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 没有在代码的其他任何地方设置。为什么会这样?


附带说明一下,我了解到我似乎不需要该变量,但我仍然很好奇为什么会这样。

最佳答案

在您的 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 运行,您就会知道所有这三个都在那里。

关于c# - 无法跟踪什么正在神秘地改变变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35537039/

相关文章:

c# - 将 String 类型的扩展方法编写为 ( String.Extension NOT "String".Extension)

c# - 棋子的 future 流动性

c# - .NET 中的 System.nanoTime() 等效于什么?

c# - 银光 2 : INotifyPropertyChanged on dynamically created object?

unity3d - 如何在 Unity 中将 Skybox 设置为我的背景?

Git LFS 与 Google Drive、Dropbox 等?

c# - activeSelf 返回 true 且 gameobject 为 false

xcode - 从 C# 调用纯 C 函数时,首先是 DllNotFoundException,然后是 EntryPointNotFoundException

unity3d - 在 Unity3D 中, "setting"网格的边界会做什么或实现什么?

c# - Unity : Do I have to learn one, 或两者(C#、UnityScript)