2016-06-08 51 views
2

我在Unity中創建2D宇宙飛船遊戲。我有一個標題爲「Player」的對象,並附有此腳本。在腳本中,我代表遊戲者的船這個類:List.Count引發空引用異常

public class Ship : MonoBehaviour 
{ 
    public List<Weapon> weaponsList; 

    void Start() 
    { 
     weaponsList = new List<Weapon>(); 
     weaponsList.Add(new Weapon()); 
     weaponsList.Add(new Weapon()); 
    } 
} 

這個階級(在同一腳本中)代表一種武器:

public class Weapon 
{ 
    //properties here 
} 

現在,當我嘗試引用weaponsList得到List.Count使用此代碼(來自不同的腳本),它拋出一個NullReferenceException,稱未將對象引用設置到對象的實例:

Ship ship = GameObject.Find("Player").GetComponent<Ship>(); 
if (ship.weaponsList.Count >=2) 
{ 
    //do stuff 
} 

但船上其他財產我嘗試訪問作品很好。有人可以幫忙嗎?如果您需要其他上下文或代碼,請告訴我,我會進行必要的修改。

編輯:啓動方法是Unity特有的,並且在腳本初始化時始終默認調用。

回答

1

爲了避免這種錯誤添加構造函數類

public class Ship : MonoBehaviour 
{ 
    public Ship() 
    { 
     weaponsList = new List<Weapon>(); 
    } 
    public List<Weapon> weaponsList; 

    void Start() 
    { 
     weaponsList = new List<Weapon>(); 
     weaponsList.Add(new Weapon()); 
     weaponsList.Add(new Weapon()); 
    } 
} 
+0

這解決了這個問題。我對這個問題做了一個編輯,說明在腳本初始化之前,Unity總是調用Start()方法,所以我認爲它的工作方式與構造函數相同。感謝您的建議。 –

+2

該解決方案導致'weaponList'被初始化兩次。如果在調用'Start()'方法之前有'weaponList'做了任何事情,這會導致奇怪的行爲。最好從'Start()'方法中移除第二次初始化,並且最好確保'weaponList'只能在「Ship」類中初始化一次和/或僅在內部初始化。 –

0

船隻不包含武器清單。

可避免與

Ship ship = GameObject.Find("Player").GetComponent<Ship>(); 
if (ship != null && ship.weaponsList != null && ship.weaponsList.Count >=2) 
{ 
    //do stuff 
} 

¿是方法start()方法調用了異常?

0

而不是把武器清單的初始化放在void Start()中,把它放在對象的構造函數中。然後當船被創建時,武器列表將始終以零計數進行初始化。構造函數應始終將有問題的對象置於有效狀態,以便可以使用它。有時,程序員創建Init()或Start()方法來推遲昂貴的邏輯,直到一個方法實際需要它,但在這種情況下,我肯定會將該初始化放在構造函數中。

0

Start()被稱爲構造列表。如果在訪問列表之前未調用Start(),則會顯示錯誤。我的猜測是,您正在嘗試在調用Start()之前訪問列表。

你應該考慮建立一個構造爲Ship類和放置初始化代碼有:

public class Ship : MonoBehaviour 
{ 
    public List<Weapon> weaponsList; 

    public Ship() 
    { 
     weaponsList = new List<Weapon>(); 
     weaponsList.Add(new Weapon()); 
     weaponsList.Add(new Weapon()); 
    } 
} 

此構造方法將盡快創建類的對象調用,您將不必調用一個方法顯式地獲取對象的屬性構造。

1

您的weaponsListnull如果Start()未被調用...或在某個點變爲null。更改公共變量成爲公共財產,拒絕外部呼叫者改變內部列表:

public class Ship : MonoBehaviour 
{ 
    public List<Weapon> weaponsList { get; private set; } 
    public Ship() 
    { 
     weaponsList = new List<Weapon>(); 
    } 
    ... 
} 

這可能會在應用程序的其他部分創建編譯器錯誤。這些錯誤可能是爲什麼weaponsList變成null的原因。

在更好的編碼實踐方面的一些建議物業改成這樣:

public IList<IWeapon> Weapons { get; private set; } 
  • 更改List到的接口。
  • Weapon更改爲IWeapon
  • 使用帕斯卡符號(Weapons,而不是weapons)。在名稱
  • 避免類型:Weapons,不WeaponsList(這是一個列表是顯而易見的)