The same field name is serialized multiple times in the class or its parent class. Как исправить ошибку?

Ссылка скопирована
1 ответ

У меня есть компонент Entity

public class Entity : MonoBehaviour {     [SerializeField] private EntityScriptableObject _scriptableObject;      public EntityScriptableObject ScriptableObject => _scriptableObject; }

public class Entity : MonoBehaviour { [SerializeField] private EntityScriptableObject _scriptableObject; public EntityScriptableObject ScriptableObject => _scriptableObject; }

И класс Document который от него унаследован

public class Document : Entity {     [SerializeField] private DocumentScriptableObject _scriptableObject;      public new DocumentScriptableObject ScriptableObject => _scriptableObject; }

public class Document : Entity { [SerializeField] private DocumentScriptableObject _scriptableObject; public new DocumentScriptableObject ScriptableObject => _scriptableObject; }

С Entity проблем не возникает, но вот при добавлении компонента Document на объект Unity выдаёт такую ошибку:

The same field name is serialized multiple times in the class or its parent class. This is not supported: Base(MonoBehaviour) _scriptableObject.

The same field name is serialized multiple times in the class or its parent class. Как исправить ошибку?

Также в инспекторе дублируется поле _scriptableObject

The same field name is serialized multiple times in the class or its parent class. Как исправить ошибку?

Как я понимаю проблема возникает из-за того что поля с одинаковым названием я пытаюсь сериализовать в базовом и наследуемом классах. Возникает вопрос можно ли (и нужно ли) исправить эту ошибку, ведь код, судя по всему, компилируется и работает так как я и задумывал. Также меня больше беспокоит то что в инспекторе дублируются поля, хотя когда я пытаюсь передать туда ссылку на объект то она передается в оба поля сразу. Это баг юнити или это из-за того что я не скрываю поле базового класса? Если дело в этом то почему тогда тип полей одинаковый в инспекторе хотя в базовом и наследуемом классах они разные? Не вызовет ли это проблем в дальнейшем если так это и оставить?

Дополнительно:

Можно сделать разные имена полей в базовом и производном классах

  • Александр Ананьев, если изменить имена , то появляется другая проблема.

    The same field name is serialized multiple times in the class or its parent class. Как исправить ошибку?

    Теперь из-за того что поле базового класса также сериализуется - в инспекторе появляются оба поля из базового класса и из класса компонента. Мой код не предполагает что в компоненте Document я могу использовать ссылку другого типа кроме DocumentScriptableObject. А если просто оставить поле пустым, то при взаимодействии с объектом летят NullReferenceException-ы. Я пробовал скрывать поле базового класса делая его protected, а в наследуемом классе использовал модификатор new. Но тогда возвращается первая проблема с ошибкой сериализации

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

    А какую задачу ты решаешь? Почему два разных поля (в родительском и дочернем классе и с разными типами) имеют одно и то же имя?

  • Gwinterion,

    Теперь из-за того что поле базового класса также сериализуется - в инспекторе появляются оба поля из базового класса и из класса компонента.

    Если для тебя это проблема, значит изначально у тебя были архитектурные проблемы.

    Вместо класса, вероятно, тебе нужно использовать интерфейс в котором будет обобщённое свойство для ScriptableObject

  • если еще не нашли решения..
    и сложно придумать другую "архитектуру".. вопросы:
    - дерево родителя и потомков? если есть иерархия более одного уровня:
    - у вас может быть ошибка в последовательности выяснения "потомка"
    - имхо один родитель, при чем virtual
    - использование интерфейсов (но не конфликт имени/типа поля!! ;)
    - и гарантия десирализации в нужный класс
    .. вы же пытаетесь сделать нечто вроде конвейера "скриптования"? (очень очень много лет назад пытался использовать такой подход.. мое работало )).. но TVision приехал очень быстро.. и наработки потеряли смысл )))

    • Я решил всё-таки немного изменить архитектуру, так как основная проблема была в ней, а всё остальное и, в том числе ошибка в юнити возникало уже как следствие. Может кому-то окажется полезным, не уверен насколько эта идея лучше, но для логики которую я задумал рабочим вариантом стало такое решение:

      Я избавился от наследования классов ScriptableObject, так что теперь иерархию наследования имеют только объекты Entity, Item и Document.

      public class EntityScriptableObject : ScriptableObject {     [SerializeField] private EntityType _type;     [SerializeField] private string _name;     [SerializeField] private string _raycastFeedbackText;     [SerializeField] private GameObject _prefab;      public EntityType Type => _type;     public string Name => _name;     public string RaycastFeedbackText => _raycastFeedbackText;     public GameObject Prefab => _prefab; }

      public class EntityScriptableObject : ScriptableObject { [SerializeField] private EntityType _type; [SerializeField] private string _name; [SerializeField] private string _raycastFeedbackText; [SerializeField] private GameObject _prefab; public EntityType Type => _type; public string Name => _name; public string RaycastFeedbackText => _raycastFeedbackText; public GameObject Prefab => _prefab; }

      public class ItemScriptableObject : ScriptableObject {     [SerializeField] private ItemType _type;     [SerializeField] private string _description;     [SerializeField] private string _raycastFeedbackText;     [SerializeField] private Sprite _sprite;      public ItemType Type => _type;     public string Description => _description;     public string RaycastFeedbackText => _raycastFeedbackText;     public Sprite Sprite => _sprite; }

      public class ItemScriptableObject : ScriptableObject { [SerializeField] private ItemType _type; [SerializeField] private string _description; [SerializeField] private string _raycastFeedbackText; [SerializeField] private Sprite _sprite; public ItemType Type => _type; public string Description => _description; public string RaycastFeedbackText => _raycastFeedbackText; public Sprite Sprite => _sprite; }

      public class DocumentScriptableObject : ScriptableObject {     [SerializeField] private DocumentType _type;     [SerializeField] private string _text;     [SerializeField] private string _raycastFeedbackText;      public DocumentType Type => _type;     public string Text => _text;     public string RaycastFeedbackText => _raycastFeedbackText; }

      public class DocumentScriptableObject : ScriptableObject { [SerializeField] private DocumentType _type; [SerializeField] private string _text; [SerializeField] private string _raycastFeedbackText; public DocumentType Type => _type; public string Text => _text; public string RaycastFeedbackText => _raycastFeedbackText; }

      public class Entity : MonoBehaviour {     [SerializeField] private EntityScriptableObject _entityScriptableObject;     public EntityScriptableObject EntityScriptableObject => _entityScriptableObject;      public virtual void Interact(){}     public void StopInteraction(){} }

      public class Entity : MonoBehaviour { [SerializeField] private EntityScriptableObject _entityScriptableObject; public EntityScriptableObject EntityScriptableObject => _entityScriptableObject; public virtual void Interact(){} public void StopInteraction(){} }

      public class Item : Entity {     [SerializeField] private ItemScriptableObject _itemScriptableObject;     public ItemScriptableObject ItemScriptableObject => _itemScriptableObject;      public Item (ItemScriptableObject scriptableObject)     {         _itemScriptableObject = scriptableObject;     }      public void Use(){}     public override void Interact(){} }

      public class Item : Entity { [SerializeField] private ItemScriptableObject _itemScriptableObject; public ItemScriptableObject ItemScriptableObject => _itemScriptableObject; public Item (ItemScriptableObject scriptableObject) { _itemScriptableObject = scriptableObject; } public void Use(){} public override void Interact(){} }

      public class Document : Entity {     [SerializeField] private DocumentScriptableObject _documentScriptableObject;     public DocumentScriptableObject DocumentScriptableObject => _documentScriptableObject;      public void Read(){}     public override void Interact(){} }

      public class Document : Entity { [SerializeField] private DocumentScriptableObject _documentScriptableObject; public DocumentScriptableObject DocumentScriptableObject => _documentScriptableObject; public void Read(){} public override void Interact(){} }

      Метод Interact в наследниках переопределяю так как по задумке объект одного и того же типа (например ключ) может как быть предметом, и его можно будет подобрать и использовать, так может и просто лежать где-нибудь, но подобрать его уже нельзя, хотя всё ещё можно как-либо взаимодействовать, например осмотреть.

    • Gwinterion, стабильно работает? ))
      так держать! ;)
    • Gwinterion, ну и мало ли.. если не видели https://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D0%B1%D...
      .. это не единственная парадигма, но именно для конвейера стоит понимать ;)

    Ответы:

    Простите, пожалуйста, но это очень глупый вопрос. Вы C# вообще учили?

    Вот ваш класс:

    public class Entity : MonoBehaviour {     [SerializeField] private EntityScriptableObject _scriptableObject;      public EntityScriptableObject ScriptableObject => _scriptableObject; }

    public class Entity : MonoBehaviour { [SerializeField] private EntityScriptableObject _scriptableObject; public EntityScriptableObject ScriptableObject => _scriptableObject; }

    И вам же четко пишет, что у вас два поля с одинаковыми именами. Вот:

    [SerializeField] private EntityScriptableObject _scriptableObject;

    [SerializeField] private EntityScriptableObject _scriptableObject;

    И вот:

    public EntityScriptableObject ScriptableObject => _scriptableObject;

    public EntityScriptableObject ScriptableObject => _scriptableObject;

    • Если вы хотели привести в пример два поля, то привели в пример поле и свойство. Это разные вещи... И ошибка не в этом, у них даже имена разные
    • Gwinterion, действительно разные?

      The same field name is serialized multiple times in the class or its parent class. Как исправить ошибку?

    • Gwinterion, я знаю, что поле и свойство это разные вещи, так у вас не может быть два элемента с одинаковыми именам
    • Nik Faraday, Так то что вы выделили это вообще тип а не имя
    • И вам же четко пишет, что у вас два поля с одинаковыми именами. Вот:
      [SerializeField] private EntityScriptableObject _scriptableObject;

      И вот:
      public EntityScriptableObject ScriptableObject => _scriptableObject;

      Погоди, но имена у них разные.
      1. _scriptableObject
      2. ScriptableObject
      А второе - вообще свойство, а не поле.
      И ошибка идёт не от компилятора C#, а от Unity

    • Nik Faraday, на скриншоте выделены типы, а не имена.
    • Василий Банников, Gwinterion, да, тут прошу прощения, утром не проснулся) Моя ошибка
    • Василий Банников, тем не менее, первое желание - понять целевую логику..
      второе - упростить ее, по возможности
      ... пока что все от ТС не очень этому способствует
    • Василий Банников,
      [SerializeField] private EntityScriptableObject _scriptableObject;

      [SerializeField] private EntityScriptableObject _scriptableObject;

      [SerializeField] private DocumentScriptableObject _scriptableObject;

      [SerializeField] private DocumentScriptableObject _scriptableObject;

    • Василий Банников, я может тоже "не проснулся".. но в обоих объявлениях, до сих пор вижу одно имя
    • Василий Банников, да еще и декларацию с разным типом... или атрибутам такое позволено?
    • #, ну так одно в родительском, а другое в дочернем.
    • Василий Банников, ... если это атрибут ))
    • #, не понимаю. Атрибут тут никак не влияет.
    • Василий Банников, но и не метод... поля разве уже можно переопределять? ))
    • #, нельзя. Просто будет отдельно base._fieldName и this._fieldName
    • Василий Банников, полагаете, в данном случае строгости Unity?
    • #, постараюсь объяснить логику которую задумал :)

      Все объекты в сцене с которыми может взаимодействовать игрок - это некие сущности Entity. Есть также наследуемые объекты Item и Document.

      public class Entity : MonoBehaviour {     [field: SerializeField]     public virtual EntityScriptableObject ScriptableObject     {         get;         private set;     }      public void Interact()     {         Transform interactionPoint;          switch (ScriptableObject.Type)         {             case EntityType.Key:                 Player.Inventory.Add(this as Item);                 Destroy(gameObject);                  break;             case EntityType.VideoTape:                 Player.Inventory.Add(this as Item);                 Destroy(gameObject);                  break;             case EntityType.Note:                 Player.Journal.Add(this as Document);                  Destroy(gameObject);                  break;             case EntityType.Painting:                 GameManager.ChangeTypeOfControll(TypesOfControl.InspectionControll);                 ObjectInspectorController.Instance.enabled = true;                 ObjectInspectorController.Instance.Initialize(this);                  break;             case EntityType.TV:                 GameManager.PauseGame();                  interactionPoint = InteractionPoints.Instance.TV.transform;                 InteractionController.Instance.InteractionPoint = interactionPoint;                 InteractionController.Instance.CurrentInteraction = InteractionType.TV;                 InteractionController.Instance.MoveToInteractionPoint();                  InteractionController.Instance.OnStopInteraction += StopInteraction;                  UIController.Instance.OpenInventory();                 PlayerController.Instance.enabled = false;                  break;             case EntityType.Door:                 DoorController door = gameObject.GetComponent<DoorController>();                  if (door.IsOpen)                     door.CloseDoor();                 else                     door.OpenDoor();                  break;             case EntityType.SafeDigital:                 GameManager.PauseGame();                 GameManager.ChangeTypeOfControll(TypesOfControl.InteractionControl);                  interactionPoint = InteractionPoints.Instance.SafeDigital.transform;                 InteractionController.Instance.InteractionPoint = interactionPoint;                 InteractionController.Instance.CurrentInteraction = InteractionType.SafeNumeric;                 InteractionController.Instance.MoveToInteractionPoint();                  InteractionController.Instance.OnStopInteraction += StopInteraction;                  PlayerController.Instance.enabled = false;                 CameraController.Instance.enabled = false;                  Cursor.lockState = CursorLockMode.None;                 Cursor.visible = true;                  gameObject.GetComponentInChildren<SafeDoor>().enabled = true;                  break;             case EntityType.SafePadlock:                 GameManager.PauseGame();                 GameManager.ChangeTypeOfControll(TypesOfControl.InteractionControl);                  interactionPoint = InteractionPoints.Instance.SafePadlock.transform;                 InteractionController.Instance.InteractionPoint = interactionPoint;                 InteractionController.Instance.CurrentInteraction = InteractionType.SafePadlock;                 InteractionController.Instance.MoveToInteractionPoint();                  InteractionController.Instance.OnStopInteraction += StopInteraction;                  PlayerController.Instance.enabled = false;                 CameraController.Instance.enabled = false;                  Cursor.lockState = CursorLockMode.None;                 Cursor.visible = true;                  gameObject.GetComponentInChildren<Padlock>().enabled = true;                  break;             default:                 break;         }     }     public void StopInteraction()     {         switch (ScriptableObject.Type)         {             case EntityType.Key:                 break;             case EntityType.VideoTape:                 break;             case EntityType.Note:                 break;             case EntityType.Painting:                 break;             case EntityType.TV:                 InteractionController.Instance.OnStopInteraction -= StopInteraction;                  InteractionController.Instance.ReturnToInteractionPosition();                 InteractionController.Instance.CurrentInteraction = InteractionType.None;                  GameManager.ResumeGame();                  break;             case EntityType.Door:                 break;             case EntityType.SafeDigital:                 gameObject.GetComponentInChildren<SafeDoor>().enabled = false;                  Cursor.lockState = CursorLockMode.Locked;                 Cursor.visible = false;                  PlayerController.Instance.enabled = true;                 CameraController.Instance.enabled = true;                  InteractionController.Instance.OnStopInteraction -= StopInteraction;                  InteractionController.Instance.CurrentInteraction = InteractionType.None;                 InteractionController.Instance.ReturnToInteractionPosition();                  GameManager.ChangeTypeOfControll(TypesOfControl.PlayerControl);                 GameManager.ResumeGame();                  break;             case EntityType.SafePadlock:                 Cursor.lockState = CursorLockMode.Locked;                 Cursor.visible = false;                  PlayerController.Instance.enabled = true;                 CameraController.Instance.enabled = true;                  InteractionController.Instance.OnStopInteraction -= StopInteraction;                  InteractionController.Instance.CurrentInteraction = InteractionType.None;                 InteractionController.Instance.ReturnToInteractionPosition();                  GameManager.ChangeTypeOfControll(TypesOfControl.PlayerControl);                 GameManager.ResumeGame();                  break;             default:                 break;         }     } }

      public class Entity : MonoBehaviour { [field: SerializeField] public virtual EntityScriptableObject ScriptableObject { get; private set; } public void Interact() { Transform interactionPoint; switch (ScriptableObject.Type) { case EntityType.Key: Player.Inventory.Add(this as Item); Destroy(gameObject); break; case EntityType.VideoTape: Player.Inventory.Add(this as Item); Destroy(gameObject); break; case EntityType.Note: Player.Journal.Add(this as Document); Destroy(gameObject); break; case EntityType.Painting: GameManager.ChangeTypeOfControll(TypesOfControl.InspectionControll); ObjectInspectorController.Instance.enabled = true; ObjectInspectorController.Instance.Initialize(this); break; case EntityType.TV: GameManager.PauseGame(); interactionPoint = InteractionPoints.Instance.TV.transform; InteractionController.Instance.InteractionPoint = interactionPoint; InteractionController.Instance.CurrentInteraction = InteractionType.TV; InteractionController.Instance.MoveToInteractionPoint(); InteractionController.Instance.OnStopInteraction += StopInteraction; UIController.Instance.OpenInventory(); PlayerController.Instance.enabled = false; break; case EntityType.Door: DoorController door = gameObject.GetComponent<DoorController>(); if (door.IsOpen) door.CloseDoor(); else door.OpenDoor(); break; case EntityType.SafeDigital: GameManager.PauseGame(); GameManager.ChangeTypeOfControll(TypesOfControl.InteractionControl); interactionPoint = InteractionPoints.Instance.SafeDigital.transform; InteractionController.Instance.InteractionPoint = interactionPoint; InteractionController.Instance.CurrentInteraction = InteractionType.SafeNumeric; InteractionController.Instance.MoveToInteractionPoint(); InteractionController.Instance.OnStopInteraction += StopInteraction; PlayerController.Instance.enabled = false; CameraController.Instance.enabled = false; Cursor.lockState = CursorLockMode.None; Cursor.visible = true; gameObject.GetComponentInChildren<SafeDoor>().enabled = true; break; case EntityType.SafePadlock: GameManager.PauseGame(); GameManager.ChangeTypeOfControll(TypesOfControl.InteractionControl); interactionPoint = InteractionPoints.Instance.SafePadlock.transform; InteractionController.Instance.InteractionPoint = interactionPoint; InteractionController.Instance.CurrentInteraction = InteractionType.SafePadlock; InteractionController.Instance.MoveToInteractionPoint(); InteractionController.Instance.OnStopInteraction += StopInteraction; PlayerController.Instance.enabled = false; CameraController.Instance.enabled = false; Cursor.lockState = CursorLockMode.None; Cursor.visible = true; gameObject.GetComponentInChildren<Padlock>().enabled = true; break; default: break; } } public void StopInteraction() { switch (ScriptableObject.Type) { case EntityType.Key: break; case EntityType.VideoTape: break; case EntityType.Note: break; case EntityType.Painting: break; case EntityType.TV: InteractionController.Instance.OnStopInteraction -= StopInteraction; InteractionController.Instance.ReturnToInteractionPosition(); InteractionController.Instance.CurrentInteraction = InteractionType.None; GameManager.ResumeGame(); break; case EntityType.Door: break; case EntityType.SafeDigital: gameObject.GetComponentInChildren<SafeDoor>().enabled = false; Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; PlayerController.Instance.enabled = true; CameraController.Instance.enabled = true; InteractionController.Instance.OnStopInteraction -= StopInteraction; InteractionController.Instance.CurrentInteraction = InteractionType.None; InteractionController.Instance.ReturnToInteractionPosition(); GameManager.ChangeTypeOfControll(TypesOfControl.PlayerControl); GameManager.ResumeGame(); break; case EntityType.SafePadlock: Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; PlayerController.Instance.enabled = true; CameraController.Instance.enabled = true; InteractionController.Instance.OnStopInteraction -= StopInteraction; InteractionController.Instance.CurrentInteraction = InteractionType.None; InteractionController.Instance.ReturnToInteractionPosition(); GameManager.ChangeTypeOfControll(TypesOfControl.PlayerControl); GameManager.ResumeGame(); break; default: break; } } }

      public class Item : Entity {     [SerializeField] private ItemScriptableObject _scriptableObject;     public override EntityScriptableObject ScriptableObject => _scriptableObject;      public void Use()     {         switch (_scriptableObject.Type)         {             case EntityType.Key:                 Player.Inventory.Remove(this);                 Debug.Log("Key used.");                  break;             case EntityType.VideoTape:                 if (InteractionController.Instance.CurrentInteraction != InteractionType.TV)                     return;                  Player.Inventory.Remove(this);                 Debug.Log("Tape inserted.");                  break;             case EntityType.Note:                 break;             case EntityType.Painting:                 break;             case EntityType.TV:                 break;             case EntityType.Door:                 break;             case EntityType.SafeDigital:                 break;             case EntityType.SafePadlock:                 break;             default:                 break;         }     } }

      public class Item : Entity { [SerializeField] private ItemScriptableObject _scriptableObject; public override EntityScriptableObject ScriptableObject => _scriptableObject; public void Use() { switch (_scriptableObject.Type) { case EntityType.Key: Player.Inventory.Remove(this); Debug.Log("Key used."); break; case EntityType.VideoTape: if (InteractionController.Instance.CurrentInteraction != InteractionType.TV) return; Player.Inventory.Remove(this); Debug.Log("Tape inserted."); break; case EntityType.Note: break; case EntityType.Painting: break; case EntityType.TV: break; case EntityType.Door: break; case EntityType.SafeDigital: break; case EntityType.SafePadlock: break; default: break; } } }

      public class Document : Entity {     [SerializeField] private DocumentScriptableObject _scriptableObject;     public override EntityScriptableObject ScriptableObject => _scriptableObject;      public void Read()     {         switch (ScriptableObject.Type)         {             case EntityType.Key:                 break;             case EntityType.VideoTape:                 break;             case EntityType.Note:                 DocumentInspectorController.Instance.enabled = true;                 DocumentInspectorController.Instance.Initialize(_scriptableObject.Text);                  break;             case EntityType.Painting:                 break;             case EntityType.TV:                 break;             case EntityType.Door:                 break;             case EntityType.SafeDigital:                 break;             case EntityType.SafePadlock:                 break;             default:                 break;         }     } }

      public class Document : Entity { [SerializeField] private DocumentScriptableObject _scriptableObject; public override EntityScriptableObject ScriptableObject => _scriptableObject; public void Read() { switch (ScriptableObject.Type) { case EntityType.Key: break; case EntityType.VideoTape: break; case EntityType.Note: DocumentInspectorController.Instance.enabled = true; DocumentInspectorController.Instance.Initialize(_scriptableObject.Text); break; case EntityType.Painting: break; case EntityType.TV: break; case EntityType.Door: break; case EntityType.SafeDigital: break; case EntityType.SafePadlock: break; default: break; } } }

      Так как Item содержит метод Use, а Document содержит метод Read, читать можно только объекты типа Document, использовать только Item, а взаимодействовать с любыми Entity. Изначально классы этих объектов были абстрактными и содержали свойства которые описывали эти объекты (название, описание, спрайт и т.д.), и от каждого объекта наследовали уже конкретные классы. Например от класса Item наследовали классы Key и VidoTape. Для хранения данных всех сущностей я изначально использовал использовал статический класс единственным свойством, которое являлось Dictionary. В нём я создавал экземпляры классов и через конструкторы задавал им свойства. Но сейчас для удобства решил вместо этого как хранилище данных использовать ScriptableObject-ы. А весь функционал реализовать в классах которые до этого были абстрактными используя switch по типам сущностей.

    • #, Вот код классов ScriptableObject.
      public class EntityScriptableObject : ScriptableObject {     [SerializeField] private EntityType _type;     [SerializeField] private string _displayName;     [SerializeField] private string _description;     [SerializeField] private string _raycastFeedbackText;     [SerializeField] private GameObject _prefab;      public EntityType Type => _type;     public string DisplayName => _displayName;     public string Description => _description;     public string RaycastFeedbackText => _raycastFeedbackText;     public GameObject Prefab => _prefab; }

      public class EntityScriptableObject : ScriptableObject { [SerializeField] private EntityType _type; [SerializeField] private string _displayName; [SerializeField] private string _description; [SerializeField] private string _raycastFeedbackText; [SerializeField] private GameObject _prefab; public EntityType Type => _type; public string DisplayName => _displayName; public string Description => _description; public string RaycastFeedbackText => _raycastFeedbackText; public GameObject Prefab => _prefab; }

      public class ItemScriptableObject : EntityScriptableObject {     [SerializeField] private Sprite _sprite;      public Sprite Sprite => _sprite; }

      public class ItemScriptableObject : EntityScriptableObject { [SerializeField] private Sprite _sprite; public Sprite Sprite => _sprite; }

      public class DocumentScriptableObject : EntityScriptableObject {     [SerializeField] private string _text;      public string Text => _text; }

      public class DocumentScriptableObject : EntityScriptableObject { [SerializeField] private string _text; public string Text => _text; }

      По идее данная реализация не предполагает что допустим в объект типа Document может попасть ссылка на ItemScriptableObject. Так что я пытался явно указать ссылки каких типов может принимать тот или иной объект но столкнулся с проблемами описанными выше

    • Gwinterion, одним словом, переименнуюйте _scriptableObject во что-то другое, что бы не было конфликта имён
    • Nik Faraday, Gwinterion, склонен поддержать..
    • Василий Банников, спасибо за ликбез.. но есть сомнения, всегда ли это удобно..
    • Gwinterion, далее [SerializeField] с одним именем для родителя и потомка, еще более сомнительно. если сериализуете, то как десериализуете? в конкретный тип? или в object? или есть автоопределение?
      ... если не очень "авто", то конфликт типов все более вероятен..
    • Gwinterion,

      постараюсь объяснить логику которую задумал :)

      ок. благие намерения в целом все более понятны..
      во что сериализуете? json/bson/bd?
      у вас львиная часть кода пытается определить "а что мы десериализовали"?
      .. и учитывая количество ветвлений, риск ошибки уж больно быстро растет..
      (пока не предлагаю решений, просто пытаюсь увидеть слабое место

    • Gwinterion,

      Вместо класса, вероятно, тебе нужно использовать интерфейс в котором будет обобщённое свойство для ScriptableObject

      от Василий Банников, скорее ближе к решению.. но

      во что сериализуете? json/bson/bd?

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

      ps вспомнил - двумерный массив строк, десереализовался в одномерный... обидно было ))

    • Gwinterion, ну и "топорный вариант" - сериализовать строго по типам (бд - таблицы, json - да хоть файлы)..
      если очередность "скриптабельных" объектов, при восстановлении, имеет значение - метки времени?..
      ... может это поможет обойти "узкое" место?... отработать дальнейшую логику.. а к этому вопросу возвращаться по мере роста эрудиции/навыков? .. удачи ))
    • Gwinterion, ну и возможно, даже макет, если продебажить в студии.. не факт что это одно и тоже с юнинити... если не подводит память - юнити основан на mono (далее кросскомпиляция в плюсы, потом в бинарный код)...
      ... если бы юнити поддерживал консольные и асп проекты... я бы давно переехал туда )))
    Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Виктор Sys Ответ

    Для исправления ошибки, когда одно и то же имя поля сериализуется несколько раз в классе или его родительском классе, вам необходимо внимательно просмотреть структуру классов и убедиться, что каждое поле имеет уникальное имя.

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

    Пример:

    class ParentClass {
        public $field = 'parent';
    }
     
    class ChildClass extends ParentClass {
        public $field = 'child'; // переопределение поля
    }

    class ParentClass { public $field = 'parent'; } class ChildClass extends ParentClass { public $field = 'child'; // переопределение поля }

    Если у вас несколько родительских классов, в которых объявлено одно и то же поле, убедитесь, что в каждом дочернем классе, которые наследуют эти родительские классы, поле переопределено с уникальным именем.

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

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

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно