我有一个带有网格布局的面板,我在其中放置预制文本对象的实例化克隆。
视觉计时器表示的每个实例都有一个附加的计时器脚本。
以及将这些文本对象添加到列表(面板)的按钮:
按下按钮时,我从新计时器调用 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
方法(如果有的话),然后调用 StartTimer
将 isStarted
设置为 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;
}
这是凭内存进行的,因此可以在您的实例中确认这一点。但是,以下链接解释了何时调用 Awake
和 Start
。
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/