2014-11-08 223 views
0

嗨我是新來的Unity遊戲引擎,我正在創建一個3D射擊遊戲。在等級1中,我想在一定時間內射擊5個敵人,比如30秒。在完成1級後,我想進入等級2,我的總敵人數爲10,並且想要在60秒內殺死它,如果失敗,遊戲結束。我爲它寫了一些腳本,但它有點作用,但它並不完美,因爲在開始第2級之後,遊戲變得緩慢,並且在遊戲結束後,第2級再次重新啓動,但不是默認值10個敵人,而是從沒有。在比賽結束時達到。我的遊戲需要一些想法和良好的邏輯和腳本。這是我的代碼。需要我的Android遊戲的邏輯

public class Status : MonoBehaviour 
{ 

    public static int TotalZombies=5; 
    public static float timeLeft=25.0f; 

// destry this game object. 
      Destroy (this.gameObject); 
      TotalZombies--; 
      } 

,這裏是我的地方,我處理我的水平和時間等其他腳本

using UnityEngine; 
using System.Collections; 

public class Generate : MonoBehaviour { 
    public GUIText Zombiesobject; 
    public string zombiesscore; 
    public GUIText countdown; 
    // Use this for initialization 
    void Start() { 

    } 

    // Update is called once per frame 
    void Update() { 
     zombiesscore = "Zombies Left: " + Status.TotalZombies.ToString(); 
     Zombiesobject.text = (zombiesscore); 

     Status.timeLeft -= Time.deltaTime; 
     if (Status.timeLeft <= 0.0f && Status.TotalZombies > 0) 
     { 
      countdown.text = "Game Over"; 
      Application.LoadLevel(Application.loadedLevel); 
} 
     else if (Status.timeLeft <= 10.0f && Status.TotalZombies > 0) 
     { 
      countdown.text = "Time left = " + (int)Status.timeLeft + " seconds" + " \n You are running out of time!"; 
     } 
     else if (Status.timeLeft > 0.0f && Status.TotalZombies <= 0) { 
       countdown.text = "You win!"; 
       Application.LoadLevel("level 2"); 
       Status.TotalZombies=10; 
       Status.timeLeft=59.0f; 
     } 
     else 
     { 
      countdown.text = "Time left = " + (int)Status.timeLeft + " seconds"; 
     } 
    } 
} 
+0

它也會在遊戲結束後掛起。 – user3866627 2014-11-08 12:03:17

回答

1

你的問題是,你使用static變量。 static完全像全局變量。唯一的區別是你需要通過一個Class名稱來訪問它們。

那究竟是什麼意思?當你加載你的遊戲,並且當這個類本身被加載時,靜態變量被創建和初始化。在你的情況下,它是TotalZombies設置爲5timeLeft25f

但是隻要你的遊戲運行,這些變量就會一直存在,並且永遠不會被重新初始化。即使你做了Application.LoadLevel這些變量和它們的值仍然存在。

這意味着如果你改變這些變量,並重新加載你的水平TotalZombiestimeLeft仍然有他們的最後值。

因此,我鼓勵永遠不要使用static變量。他們很容易引入難以發現的錯誤。讓我們假設對代碼進行簡單修復。

您還爲您的Start()方法添加初始化。例如,在您添加的Status類中。

void Start() { 
    TotalZombies = 5; 
    timeLeft  = 25.0f; 
} 

在你的情況下,它可以完全解決問題,但你也可以說這只是偶然或運氣。

在Unity中,不存在調用Start()的順序。例如,在加載場景時,可能會發生以下情況:您的Generate類中的Start方法首先被調用。如果您在Start中使用Status.TotalZombiesStatus.timeleft初始化Generate中的某些內容,則仍然存在您的初始化錯誤,因爲它使用了上一次運行的變量。問題是Unity有時可能會首先在Generate.Start()之前首先執行Status.Start()。這將導致只有sometimes發生並且極難調試的錯誤。

如果您知道上述內容,您也可以將您的初始化設置爲Awake方法。因爲在任何Start方法之前將調用Awake方法。所以這將是一個更好的解決方案。

但還存在其他問題。例如,讓我們看看你的Generate.Update()方法。例如,您直接在Update方法中執行Status.timeLeft -= Time.deltaTime;。但是,例如,如果您的遊戲中有多個GameObjects,其中包含Generate組件,則表示timeLeft將在單個幀中多次減少。如果您有兩個組件,則意味着您的時間將快兩倍。

因此,即使把初始化成StartAwake可以修復一些bug,但你仍然有不同的問題static小號

這就是爲什麼我鼓勵不使用static根本原因。那麼如何解決這個問題?您應該創建一個類的屬性,而不是靜態的。最重要的是,你應該讓所有屬性只能從你自己的班級中設置。這也對其他代碼有影響。例如,您不能從Generate中減少timeLeft屬性。這聽起來像是一個缺點,但是它會迫使你想如何正確地改變timeLeft。在你的情況下,你並不是真的希望任何地方的任何班級都能改變timeLeft。這是一個應該不斷縮短的時間,多次縮短它只是一個錯誤。結果是。您的Status課程只應更改Update中的timeLeftTotalZombies也是如此。最好是隻有像IncrementTotalZombiesDecrementTotalZombies這樣的方法,而不是做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--; 
    } 
} 

現在IncreaseTotalZombiesDecreaseTotalZombies聽起來像是開銷,但你可以做很多額外的檢查在這裏。例如檢查計數器是否小於零。因爲當它的時候,你的代碼中有一個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 ZombiesStart Time。在這個框中,你現在可以輸入多少殭屍或你的關卡應該有多少開始時間。這些值的默認值是525。但是這些價值並沒有被用於加載你的關卡。也可以在您的關卡裝載時應用這些值,將您的Awake方法更改爲。現在

void Awake() { 
    this.TotalZombies = this._StartZombies; 
    this.TimeLeft  = this._StartTime; 
} 

this.TotalZombiesthis.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 0Element 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」之前。

+0

謝謝...有沒有什麼方法可以在Generate class中控制所有的遊戲關卡以及我的敵人的數量和時間?就像在進入等級3之前,我想把我的敵人改變爲15和15.0f? – user3866627 2014-11-08 13:40:42

+0

@user我在最後添加了它。最好的方法是,如果你不使用靜態並從其他值啓動它們,比如'_StartZombies'。通過這種方式,您可以從Unity IDE配置時間和殭屍,而不是通過代碼進行設置。通過初始化設置代碼並仍然使用靜態不是一個好方法。因爲在每次加載時,您的「喚醒」或「開始」將其重置爲默認值。它只會在'LoadLevel'之前設置靜態值並且不會用'Start'或'Awake'初始化值。 – 2014-11-08 13:46:48

+0

對不同的級別使用不同的生成類是一個好主意嗎?像生成1級,生成2級,在那裏我分別設定我的敵人和時間? – user3866627 2014-11-08 13:49:53