Json.net не может сериализовать классы, производные от Monobehaviour

Я пытаюсь сериализовать файл сохранения, но Json.net не может сериализовать классы, производные от Monobehaviour. Ошибка, которую он дает мне, выглядит следующим образом

NotSupportedException: rigidbody property has been deprecated

В этом проекте нигде не используются жесткие тела, поэтому эта ошибка меня очень смущает. Возможно, стоит отметить, что я использую старую версию Json.net(3.5.8), так как это последняя версия, которая поддерживает структуру проектов(3.5)

Сам файл сохранения не является производным от Monobehaviour, но внутри него есть соответствующие свойства. Это приводит к появлению ошибки.

Это код, который я использую для проверки сериализации, как вы можете видеть, он должен сериализовать сохранение, распечатать результат, десериализовать его, а затем снова распечатать.

 var test1 = JsonConvert.SerializeObject(SaveManager.currentSave, Formatting.Indented, new JsonSerializerSettings()
            {
                PreserveReferencesHandling = PreserveReferencesHandling.Objects
            });

            Debug.Log(test1);

            var test2 = JsonConvert.DeserializeObject<Save>(test1);

            Debug.Log(test2);

Сохранить курс

using System.Collections.Generic;
using UnityEngine;

namespace Com.BlewScreen.Woongame
{
    [System.Serializable]
    public class Save
    {
        private bool initialSave = true;

        private string saveName;

        //Player var
        private House house;
        private string districtHouseName;
        private House wantsToMove;
        private string districtWantsToMoveToName;

        [System.NonSerialized]
        public District houseDistrict;
        [System.NonSerialized]
        public District wantsToMoveToDistrict;

        private int income;
        private int health;
        private int balance;
        private int livingpleasure;
        private int regtime;
        private bool disabled;
        private bool hasPartner;
        private int kids;
        private int livingSituationCount;

        //Housing market var
        private DistrictStats a;    //Tom: Change this to "DistrictStatsA" etc. instead of just a, b, c, d, e
        private DistrictStats b;
        private DistrictStats c;
        private DistrictStats d;
        private DistrictStats e;

        private string characterIndexes;

        public string CharacterIndexes { get; set; }

        public string characterSkinTone;

        public string CharacterSkinTone { get; set; }

        public House House
        {
            get{ return house; }
            set{ house = value; }
        }
        public House WantsToMove
        {
            get{ return wantsToMove; }
            set{ wantsToMove = value; }
        }      
        public int Income
        {
            get { return income; }
            set{ income = value; }
        }
        public int Health
        {
            get{ return health; }
            set{ health = value; }
        }
        public int Balance
        {
            get{ return balance; }
            set{ balance = value;}
        }
        public int Livingpleasure
        {
            get{ return livingpleasure;}
            set{ livingpleasure = value;}
        }
        public int Regtime
        {
            get{ return regtime;}
            set{ regtime = value;}
        }
        public bool Disabled
        {
            get{ return disabled;}
            set{ disabled = value;}
        }
        public bool HasPartner
        {
            get{ return hasPartner;}
            set{ hasPartner = value;}
        }
        public int Kids
        {
            get{ return kids;}
            set{ kids = value;}
        }
        public DistrictStats A
        {
            get{ return a;}
            set{ a = value;}
        }
        public DistrictStats B
        {
            get{ return b; }
            set{ b = value;}
        }
        public DistrictStats C
        {
            get{ return c;}
            set { c = value;}
        }
        public DistrictStats D
        {
            get{ return d;}
            set{ d = value;}
        }
        public DistrictStats E
        {
            get{ return e;}
            set{ e = value; }
        }
        public string DistrictHouseName
        {
            get{ return districtHouseName;}
            set{ districtHouseName = value; }
        }
        public string DistrictWantsToMoveToName
        {
            get{ return districtWantsToMoveToName;}
            set{ districtWantsToMoveToName = value; }
        }
        public bool InitialSave
        {
            get{ return initialSave; }
            set{ initialSave = value;}
        }
        public int LivingSituationCount
        {
            get{ return livingSituationCount;}
            set{ livingSituationCount = value; }
        }
        public string SaveName
        {
            get{ return saveName; }
            set{ saveName = value; }
        }

        public Save()
        {
            InitialSave = true;
        }
        public Save(string saveName, House house, House wantsToMove, 
                    int income, int health, int balance, int livingpleasure, 
                    int regtime, bool disabled, bool hasPartner, int kids, 
                    int livingSituationCount, DistrictStats a, DistrictStats b, 
                    DistrictStats c, DistrictStats d, DistrictStats e, string characterIndexes, string characterSkinTone)
        {
            initialSave = false;
            DistrictHouseName = house.District.DistrictName;

            if (wantsToMove != null)
            {
                DistrictWantsToMoveToName = wantsToMove.District.DistrictName;

            }

            this.saveName = saveName;
            this.House = house;
            this.WantsToMove = wantsToMove;
            this.Income = income;
            this.Health = health;
            this.Balance = balance;
            this.Livingpleasure = livingpleasure;
            this.Regtime = regtime;
            this.Disabled = disabled;
            this.HasPartner = hasPartner;
            this.Kids = kids;
            this.LivingSituationCount = livingSituationCount;
            A = a;
            B = b;
            C = c;
            D = d;
            E = e;
            this.CharacterIndexes = characterIndexes;
            this.CharacterSkinTone = characterSkinTone;

        }
    }
}

Полный стек ошибок

NotSupportedException: rigidbody property has been deprecated UnityEngine.GameObject.get_rigidbody () (at C:/buildslave/unity/build/Runtime/Export/GameObject.deprecated.cs:23) (wrapper dynamic-method) UnityEngine.GameObject.Getrigidbody (object) Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue (object) Rethrow as JsonSerializationException: Error getting value from 'rigidbody' on 'UnityEngine.GameObject'. Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue (System.Object target) Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject (Newtonsoft.Json.JsonWriter writer, System.Object value, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContract collectionValueContract)

Возможный дубликат Сериализация GameObject в Unity 5

Kristóf Tóth 08.03.2019 15:39

Объекты, включаемые в сохранение, получены из GameObject? Это не имеет ничего общего с Json.Net, а скорее с устаревшими функциями единства.

Kristóf Tóth 08.03.2019 15:39

@KristófTóth, например, в доме собственности есть свойство, называемое районом, которое происходит от Monobehaviour и содержит в себе элементы GameObject.

Tom Limpens 08.03.2019 15:42

Я наткнулся на сообщение о сериализации Unity 5 GameObject, но дело в том, что в этом проекте не используются жесткие тела, поэтому также нет вызовов жестких тел.

Tom Limpens 08.03.2019 15:43

Спасибо, что это проблема, поскольку вы пытаетесь сериализовать весь объект-контейнер, в конечном итоге он достигнет устаревших свойств и выдаст исключение из-за устаревших функций. Проверьте ветку, упомянутую выше, она предоставит вам решение

Kristóf Tóth 08.03.2019 15:44

В сообщении, упомянутом выше, говорится только о том, что нельзя называть твердым телом по-старому, однако я не использую никаких жестких тел @KristófTóth.

Tom Limpens 08.03.2019 15:46
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
1 272
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы не можете сериализовать MonoBehaviour или любой компонент Unity.

Эта ошибка, скорее всего, вызвана тем, что Json.net пытается получить значение свойства .rigidbody, и, поскольку оно устарело, это вызывается.

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

Правильный. Просто сериализуйте то, что вам нужно, а не всю стрельбу.

david.pfx 23.05.2019 07:12

так как же можно сериализовать такие данные?

Mark S 25.03.2020 07:50

Есть несколько вариантов:

  • Добавьте атрибут [JsonObject(MemberSerialization = MemberSerialization.OptIn)] в класс компонента и добавьте атрибут [JsonProperty] в свойство/поле.
  • Напишите Пользовательский JsonConverter для каждого компонента.

Эти параметры не подходят для моего варианта использования, поскольку у меня есть несколько компонентов и свойств, которые нужно сериализовать. Я также хочу включить свойство name из UnityEngine.Object, но мы не можем добавить атрибут в класс.

Что я сделал, так это переопределил метод CreateProperties в моем КонтрактРезолвер.

protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
    var properties = base.CreateProperties(type, memberSerialization);
    // Only filter class that is derived from MonoBehaviour
    if (type.IsSubclassOf(typeof(MonoBehaviour)))
    {
        // Keep name property OR properties derived from MonoBehaviour
        properties = properties.Where(x => x.PropertyName.Equals("name") || x.DeclaringType.IsSubclassOf(typeof(MonoBehaviour))).ToList();
    }
    return properties;
}

Другие вопросы по теме