使静态类数据可序列化

问题描述 投票:-1回答:1

请考虑以下几点。

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#,如果你也能给我一个简单的理论上的原因,为什么不能工作,这将对我的理解有很大帮助。谢谢您!请您考虑以下问题

c# unity3d serialization static
1个回答
1
投票

首先:你的问题与一个字段被 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);
    }
}

0
投票

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上访问它们,而不需要看到实例。

© www.soinside.com 2019 - 2024. All rights reserved.