你的問題是,你使用static
變量。 static
完全像全局變量。唯一的區別是你需要通過一個Class名稱來訪問它們。
那究竟是什麼意思?當你加載你的遊戲,並且當這個類本身被加載時,靜態變量被創建和初始化。在你的情況下,它是TotalZombies
設置爲5
和timeLeft
到25f
。
但是隻要你的遊戲運行,這些變量就會一直存在,並且永遠不會被重新初始化。即使你做了Application.LoadLevel
這些變量和它們的值仍然存在。
這意味着如果你改變這些變量,並重新加載你的水平TotalZombies
和timeLeft
仍然有他們的最後值。
因此,我鼓勵永遠不要使用static
變量。他們很容易引入難以發現的錯誤。讓我們假設對代碼進行簡單修復。
您還爲您的Start()
方法添加初始化。例如,在您添加的Status
類中。
void Start() {
TotalZombies = 5;
timeLeft = 25.0f;
}
在你的情況下,它可以完全解決問題,但你也可以說這只是偶然或運氣。
在Unity中,不存在調用Start()
的順序。例如,在加載場景時,可能會發生以下情況:您的Generate
類中的Start
方法首先被調用。如果您在Start
中使用Status.TotalZombies
或Status.timeleft
初始化Generate
中的某些內容,則仍然存在您的初始化錯誤,因爲它使用了上一次運行的變量。問題是Unity有時可能會首先在Generate.Start()
之前首先執行Status.Start()
。這將導致只有sometimes
發生並且極難調試的錯誤。
如果您知道上述內容,您也可以將您的初始化設置爲Awake
方法。因爲在任何Start
方法之前將調用Awake
方法。所以這將是一個更好的解決方案。
但還存在其他問題。例如,讓我們看看你的Generate.Update()
方法。例如,您直接在Update
方法中執行Status.timeLeft -= Time.deltaTime;
。但是,例如,如果您的遊戲中有多個GameObjects
,其中包含Generate
組件,則表示timeLeft
將在單個幀中多次減少。如果您有兩個組件,則意味着您的時間將快兩倍。
因此,即使把初始化成Start
或Awake
可以修復一些bug,但你仍然有不同的問題static
小號
這就是爲什麼我鼓勵不使用static
根本原因。那麼如何解決這個問題?您應該創建一個類的屬性,而不是靜態的。最重要的是,你應該讓所有屬性只能從你自己的班級中設置。這也對其他代碼有影響。例如,您不能從Generate
中減少timeLeft
屬性。這聽起來像是一個缺點,但是它會迫使你想如何正確地改變timeLeft
。在你的情況下,你並不是真的希望任何地方的任何班級都能改變timeLeft
。這是一個應該不斷縮短的時間,多次縮短它只是一個錯誤。結果是。您的Status
課程只應更改Update
中的timeLeft
。 TotalZombies
也是如此。最好是隻有像IncrementTotalZombies
和DecrementTotalZombies
這樣的方法,而不是做Status.TotalZombies++
等等。例如您Status
類現在應該像
public class Status : MonoBehaviour {
public int TotalZombies { get; private set; }
public float TimeLeft { get; private set; }
void Awake() {
this.TotalZombies = 5;
this.TimeLeft = 25f;
}
void Update() {
this.TimeLeft -= Time.deltaTime;
}
public void IncreaseTotalZombies() {
this.TotalZombies++;
}
public void DecreaseTotalZombies() {
if (this.TotalZombies <= 0) {
throw new ApplicationException("Cannot decrease TotalZombies. Already 0. Possible Bug in your code.");
}
this.TotalZombies--;
}
}
現在IncreaseTotalZombies
或DecreaseTotalZombies
聽起來像是開銷,但你可以做很多額外的檢查在這裏。例如檢查計數器是否小於零。因爲當它的時候,你的代碼中有一個bug。例如意外增加2個TotalZombies,或者其他地方減少2個,等等。你也可以實現一個MaxTotalZombies
屬性,確保你永遠不會獲得更多的殭屍定義。如果發生這種情況,它會拋出一個異常,將它直接指向你的代碼。
識別錯誤也很容易。因爲連續增加兩次看起來是錯誤的。
status.IncreaTotalZombies();
status.IncreaTotalZombies();
,其中下面的代碼可以直接看的權利
Status.TotalZombies += 2;
但是,如果你做了以上的變化,你會看到你當前Status.TotalZombies
將不再工作。您還必須更改如何獲得Status
課程的實例。爲此,假設您在Unity中創建一個名爲Status
的GameObject。然後在你的Generate
類中添加以下內容。
private Status status;
void Awake() {
this.status = GameObject.Find("Status").GetComponent<Status>();
}
現在你可以用status.IncreaseTotalZombies()
取代Status.TotalZombies++
等。如果您只想獲取值,您仍然可以編寫status.TimeLeft
,但設置值status.TimeLeft -= Time.deltaTime
現在將引發錯誤。你不需要再設置它,因爲這是Status
類已經在他的Update
方法中已經處理的行爲。
現在在你的代碼中加入Generate
這個代碼。
Application.LoadLevel("level 2");
Status.TotalZombies=10;
Status.timeLeft=59.0f;
這沒有像預期的那樣工作。因爲當你打電話給Application.LoadLevel()
時,你的新場景被調用,它後面的線條從未被調用過。你可以解決這個問題,就是改變順序。
Status.TotalZombies=10;
Status.timeLeft=59.0f;
Application.LoadLevel("level 2");
因爲您的狀態static
值通過加載持續存在。但整個方法仍然不是很好。問題是你在代碼中硬編碼值。看來你需要不同數量的殭屍和時間每個級別。如果你想要的話,你可以添加屬性到你的Status
類,初始化你的變量,這些變量可以通過你的Unity IDE設置。例如,將以下屬性添加到Status
類中。
public int _StartZombies = 5;
public float _StartTime = 25f;
如果你在你的IDE現在添加到您的Status
類兩個文本框會出現一個名爲Start Zombies
和Start Time
。在這個框中,你現在可以輸入多少殭屍或你的關卡應該有多少開始時間。這些值的默認值是5
和25
。但是這些價值並沒有被用於加載你的關卡。也可以在您的關卡裝載時應用這些值,將您的Awake
方法更改爲。現在
void Awake() {
this.TotalZombies = this._StartZombies;
this.TimeLeft = this._StartTime;
}
this.TotalZombies
和this.TimeLeft
總是讓您在IDE中配置的值。你現在唯一需要做的就是寫。
Application.LoadLevel("SomeLevel");
而且你可以通過IDE配置殭屍的數量和時間!這也意味着你現在有可重用的組件。而且你配置了它所屬的地方!
您還描述了您需要不同的條件來加載新級別。例如,如果用戶能夠在特定時間內殺死所有殭屍,他將直接跳到級別3而不是級別2,依此類推。那麼如何在不創建許多特殊類的情況下添加這些?
首先,你需要一個自己只有一個類的數據。在你的情況下,你需要一個特定的時間和一個定義哪個級別被加載。所以你可以寫這樣的東西。
[System.Serializable]
public class LoadLevelData {
public float TimeLeft;
public string LoadLevel;
}
但在這種邏輯屬於Status
類我看來,所以你現在要做的是以下內容添加到這個類。
public LoadLevelData[] _NextLevels;
只要您將其添加到您的代碼。在Unity IDE中,您將看到帶有「光標」的「下一級」。您現在可以展開此光標,並且會出現一個Size
字段。你現在可以例如寫入2,它給你Element 0
和Element 1
。因此,Unity使您能夠創建一個對象數組,並且您可以根據需要使用您想要的任何值創建任意數量的條目!
現在,您可以用這種方法編寫LoadNextLevel
方法。
public void LoadNextLevel() {
foreach (var level in this._NextLevels) {
if (level.TimeLeft > this.TimeLeft) {
Application.LoadLevel(level.LoadLevel);
}
}
}
現在你可以在Unity IDE
Element 0:
Time Left -> 20
Next Level -> "Level 3"
Element 1:
Time Left -> 10
Next Level -> "Level 2"
配置你只需要調用status.LoadNextLevel()
當你的遊戲結束了。您可以配置IDE中的所有內容。另請注意。您填充_NextLevel數組的順序非常重要。在這種情況下,「剩餘時間」 - > 20必須在「10」之前。
它也會在遊戲結束後掛起。 – user3866627 2014-11-08 12:03:17