请考虑以下几点。
public class myClass : MonoBehaviour
{
public int i; //<- value set from inspector
static myClass()
{
Awake();
}
private static void Awake()
{
Debug.Log(i); //<- Error CS0120
}
}
这会给我带来一个错误 error CS0120: An object reference is required for the non-static field, method, or property 'myClass.i'
我就可以(根据 本页)试着用另一种方式来写。
public class myClass : MonoBehaviour
{
public int i;
static myClass()
{
Awake();
}
private static void Awake()
{
var mc = new myClass();
Debug.Log(mc.i); //<- NullReferenceException
}
}
但那会给我带来错误 NullReferenceException: Object reference not set to an instance of an object myClass.Awake ()
.
意味着我不能序列化静态变量?有什么变通的办法吗?很抱歉,但我还在适应C#,如果你也能给我一个简单的理论上的原因,为什么不能工作,这将对我的理解有很大帮助。谢谢您!请您考虑以下问题
首先:你的问题与一个字段被 serializable
或不。
这与您的实例类字段有关。i
无法从 static
上下文。就像错误所说的那样,你需要一个类的实例来访问它。不过
如上所述,类型 MonoBehaviour
不允许有任何构造函数,也不能通过 new
关键字在Unity中。唯一允许的创建组件实例的方式是通过 Instantiate
, AddComponent
的构造函数,或通过例如. new GameObject("someName", typeof(YOUR_COMPONENT));
.
你不需要一个Singleton来实现你想要的东西。听起来你实际上是想用这种方式。
public class myClass : MonoBehaviour
{
// This one you set via the Inspector
[SerializeField] private int _i;
// This is now a read-only property
// That can only be set by this class
public static int i { get; private set; }
private void Awake()
{
// Your instance can always access its static fields
// So this way you can assign the value
i = _i;
}
}
总的来说,我们需要更多的信息来了解你的实际使用情况。也有可能你可以使用一个完全静态的类,例如
public static class myClass
{
public static int i = 42;
}
这样你的字段就不会被序列化,而是可以从任何地方访问,而不需要在场景中建立一个实例。你可以简单地从另一个 MonoBehaviour
比如
public class Example : MonoBehaviour
{
private void Start()
{
Debug.Log(myClass.i);
}
}
或者你可能想让你的类根本不是静态的,而是通过正确的引用来访问它,如
[Serializable]
public class myClass
{
public int i = 42;
}
public class Example : MonoBehaviour
{
// Since it is tagged Serializable and now serialized in the Inspector
// an instance is created for this field automatically
[SerializedField] private myclass _myClass;
private void Awake()
{
Debug.Log(_myclass.i);
}
}
Unity只能序列化一个类的特定实例(monobehaviour)。静态信息是在类的所有实例之间共享的,因此不能被unity序列化。
另外,不要在你的monobehaviours中放一个构造函数,对象是由unity引擎使用自己的进程构造的,并且自动调用awake函数。你之所以会出现空引用异常,是因为awake函数是从你的构造函数中调用的,而不是从unity内部函数中调用的,而unity内部函数应该是对它进行初始化的,所以需要为它设置的东西没有设置。
你还没有说为什么你需要静态信息序列化,但如果你想使用单人方法,在unity中有几个简单的方法可以做到这一点。
class MySingleton : MonoBehaviour
{
[SerializeField] private int someDataA;
[SerializeField] private int someDataB;
public static MySingleton Instance
{
get;
private set;
}
public int SomeDataA
{
get
{
return someDataA;
}
set
{
someDataA = value;
}
}
public int SomeDataB
{
get
{
return someDataB;
}
set
{
someDataB = value;
}
}
private void Awake()
{
Instance = this;
}
}
或者
class MySingleton : MonoBehaviour
{
[SerializeField] private int someDataA;
[SerializeField] private int someDataB;
private static MySingleton instance;
public static int SomeDataA
{
get
{
return instance.someDataA;
}
set
{
instance.someDataA = value;
}
}
public static int SomeDataB
{
get
{
return instance.someDataB;
}
set
{
instance.someDataB = value;
}
}
private void Awake()
{
instance = this;
}
}
在第一个例子中,你可以通过访问MySingleton.Instance来访问组件的当前实例,并访问它的属性和函数。在第二个例子中,实例是私有的,所有的属性和函数都是静态的,所以你可以直接在MySingleton上访问它们,而不需要看到实例。