Обеспечение сериализации данных класса stati c - PullRequest
0 голосов
/ 03 мая 2020

Примите во внимание следующее:

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 ().

То есть я не могу сериализовать переменные stati c? Есть ли обходной путь? Извините, но я все еще привыкаю к ​​C#, и если бы вы могли также дать мне краткую теоретическую причину, почему она не работает, это очень помогло бы мне в понимании. Спасибо!

Ответы [ 2 ]

1 голос
/ 04 мая 2020

Прежде всего: Ваша проблема не имеет ничего общего с полем serializable или нет.

Оно скорее связано с тем, что ваше поле экземпляра класса i недоступно из контекста static , Как говорится в сообщении об ошибке, вам понадобится экземпляр вашего класса, чтобы получить к нему доступ , но

Как уже упоминалось, классы типа MonoBehaviour не могут иметь какого-либо конструктора и могут не иметь быть запущенным через ключевое слово new в Unity. Единственные разрешенные способы создания экземпляров компонентов - через Instantiate, AddComponent или через конструктор, например, new GameObject("someName", typeof(YOUR_COMPONENT));.


Вам не нужен Singleton для того, что вы хотите. Звучит так, как будто вы на самом деле хотели бы go таким образом:

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

В общем, нам понадобится больше информации, чтобы выяснить ваш фактический вариант использования здесь. Также возможно, что вы можете использовать полностью статический c класс, такой как, например,

public static class myClass
{
    public static int i = 42;
}

, это делает ваше поле не сериализованным, а просто доступным из любого места без необходимости использования экземпляра в сцене. Вы можете просто получить к нему доступ из другого MonoBehaviour, например,

public class Example : MonoBehaviour
{
    private void Start()
    {
        Debug.Log(myClass.i);
    }
}

. Или вы можете сделать так, чтобы ваш класс вообще не стал c, а вместо этого получил бы доступ к нему через правильную ссылку, например

* 1030. *
0 голосов
/ 03 мая 2020

Unity может сериализовать только указанный c экземпляр класса (монобихи поведение). Статистическая информация c распределяется между всеми экземплярами класса и поэтому не может быть сериализована единым целым.

Кроме того, не помещайте конструктор в ваши монобоги, объект создается механизмом единства с использованием его собственного процесса, и функция пробуждения вызывается автоматически. Вы получаете это исключение нулевой ссылки, потому что функция awake вызывается из вашего конструктора, а не из внутренних функций Unities, которые должны его инициализировать, поэтому вещи, которые необходимо настроить для этого, не были.

Вы не сказали, зачем вам нужно сериализовать c информацию, но если вы пытаетесь использовать одноэлементный подход, есть пара простых способов сделать это в единстве:

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 и получить доступ к своим свойствам и функциям на нем. Во втором примере экземпляр остается закрытым, и все свойства и функции устанавливаются как статичные c, так что вы можете получить к ним доступ непосредственно в MySingleton без необходимости видеть экземпляр.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...