Unity告诉我通过一个对象的实例引用,Visual Studio告诉我不要

时间:2016-11-20 11:18:35

标签: c# unity3d reference instance nullreferenceexception

所以我正在创建一个保存和加载脚本,这是它的内容:

using UnityEngine;
using System.Collections;

public class SaveLoad : MonoBehaviour {

public Player player = GameObject.FindGameObjectWithTag("Player").GetComponent<Player> ();

public void Save() {

    PlayerPrefs.SetFloat ("X", transform.position.x);
    PlayerPrefs.SetFloat ("Y", transform.position.y);
    PlayerPrefs.SetFloat ("Z", transform.position.z);

    PlayerPrefs.SetFloat("Health", Player.Health.CurrentVal);
    PlayerPrefs.SetFloat ("Exp", Player.Exp.CurrentVal);
    PlayerPrefs.SetFloat("Oxygen", Player.Oxygen.CurrentVal);
    PlayerPrefs.SetFloat("PlayerLevel", Player.PlayerLevel.CurrentVal);

    Debug.Log ("Saved");


}

public void Load() {
    float x = PlayerPrefs.GetFloat ("X");
    float y = PlayerPrefs.GetFloat ("Y");
    float z = PlayerPrefs.GetFloat ("Z");

    Player.Health.CurrentVal = PlayerPrefs.GetFloat("Health");
    Player.Exp.CurrentVal = PlayerPrefs.GetFloat("Exp");
    Player.Oxygen.CurrentVal = PlayerPrefs.GetFloat("Oxygen");
    Player.PlayerLevel.CurrentVal = PlayerPrefs.GetFloat("PlayerLevel");

    transform.position = new Vector3 (x, y, z);

    Debug.Log ("Loaded");
}
}

没有“公共播放器播放器”行的第一个版本返回了NullReferenceException,并表示通过Unity中的对象实例进行引用。现在,当我尝试这样做时(而不是(“Health”,Player.Health.CurrentVal)我使用(“Health”,player.Health.CurrentVal),在“Player”中没有资本,引用我在相同的脚本),Visual告诉我“无法使用对象的实例访问Player.Health;而是使用类型名称限定它”。正如你所看到的,我有点陷入困境。我是不是试图让玩家成为一个实例?它也有点乱,因为播放器既是游戏对象的名字又是剧本的名称。 玩家脚本:

[SerializeField] public Stat health;
public static Stat Health { get; set; }
[SerializeField] private Stat exp;
public static Stat Exp { get; set; }
[SerializeField] private Stat oxygen;
public static Stat Oxygen { get; set; }
[SerializeField] private Stat playerLevel;
public static Stat PlayerLevel { get; set; }
[SerializeField] private Text playerLevelText;

这是Stat自定义变量类:

[SerializeField] private BarPrototype bar;
[SerializeField] private float maxVal;
[SerializeField] private float currentVal;

public float CurrentVal 
{
    get 
    {
        return currentVal;
    }
    set 
    {
        this.currentVal = Mathf.Clamp (value, 0, MaxVal);
        if( bar != null )
            bar.Value = this.currentVal;
    }
}

SerializeField仅用于从检查器访问这些值。

1 个答案:

答案 0 :(得分:2)

问题是你不能像这样初始化公共成员:

public Player player = GameObject.FindGameObjectWithTag("Player").GetComponent<Player> ();

应该在Start,Awake或OnEnable方法中初始化它们。如果你把它改成下面它应该工作

public Player player;
void Start(){
    player = GameObject.FindGameObjectWithTag("Player").GetComponent<Player> ();
}

另一件事是你为什么要公开呢?如果在检查器中分配,则在Start()之后将忽略其指定的值。我建议你把它做成内部的。或者是安全的:

public Player player;
void Start(){
    if(player == null)
       player = GameObject.FindGameObjectWithTag("Player").GetComponent<Player> ();
}