List.Count 引发空引用异常

List.Count Raises Null Reference Exception

我正在 Unity 中创建一个 2D 宇宙飞船游戏。我有一个名为 "Player" 的 object,上面附有此脚本。在脚本中,我有这个 class 代表玩家的飞船:

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

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

而这个 class(在同一个脚本中)代表武器:

public class Weapon
{
    //properties here
}

现在,当我尝试使用此代码(来自不同脚本)引用 weaponsList 以获取 List.Count 时,它会抛出 NullReferenceException,提示 Object 引用未设置为 object:

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

但是我尝试访问的任何其他 属性 船都工作正常。有人可以帮忙吗?如果您需要其他上下文或代码,请告诉我,我会进行必要的修改。

编辑: start 方法是 Unity 特有的,在脚本初始化时总是默认调用。

船舶不包含武器清单。

您可以使用

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

¿是否调用了 Start() 方法?

不要将武器列表的初始化放在 void Start() 中,而是放在对象的构造函数中。然后在创建飞船时,武器列表将始终初始化为零计数。构造函数应该始终将有问题的对象置于有效状态,以便可以使用它。有时,程序员会创建 Init() 或 Start() 方法来推迟昂贵的逻辑,直到方法真正需要它为止,但在这种情况下,我肯定会将该初始化放在构造函数中。

为避免此错误 将构造函数添加到您的 class

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());
    }
}

调用Start()时构造列表。如果在访问列表之前未调用 Start(),则会出现您的错误。我的猜测是您试图在调用 Start() 之前访问该列表。

您应该考虑为 Ship class 构建构造函数并将初始化代码放在那里:

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

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

一旦创建 class 的对象,就会调用此构造函数,您不必显式调用方法来构造对象的属性。

如果 Start() 没有被调用,你的 weaponsList 就是 null ... 或者它在某个时候变成 null。将 public 变量更改为 public 属性 以拒绝外部调用者更改内部列表:

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
  • 使用 Pascal 表示法(Weapons,而不是 weapons)。
  • 避免名称中的类型:Weapons,而不是 WeaponsList(很明显这是一个列表)