Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

444
Visualizações
Unity Scriptable Object cambia el tipo de campo a un nuevo tipo basado en otro valor de campo

¿Es posible que un objeto programable tenga un campo de un tipo específico y que ese tipo se determine en función del tipo de otro campo? Por ejemplo:

 public class ItemObject : ScriptableObject { public ItemType type; public Item data = new Item(); }

ItemType es una enumeración

 public enum ItemType { Physical, Magical }

Item es una clase básica, con otras 2 clases heredadas de ella, MagicalItem y PhysicalItem.

 [System.Serializable] public class MagicalItem : Item { public string passive; public MagicalItem() { passive = ""; } } ect.

Me gustaría que ItemObject pudiera elegir en el editor entre cualquiera de estas opciones, o muchas más, a medida que agrego nuevos tipos de elementos a mi juego. No he podido encontrar una solución, pero mi idea es establecer el tipo de datos en Awake() según el tipo, pero no he podido hacer que funcione. IE algo como esto:

 private void Awake() { if(type == ItemType.Magical) { data = new MagicalItem(); } else { data = new PhysicalItem(); } }

¿Hay una mejor manera de resolver este problema?

¡Gracias!

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Me divertí resolviendo este.

El truco que encontré para esto es en realidad algo nuevo, [SerializeReference] , que hace algunas cosas, una de las cuales te permite hacer serialización polimórfica, que requiere esta pregunta.

Los principales pasos para resolver esto:

  • Agregue [SerializeReference] al campo de data .
  • Agregue un método estático que cree una nueva instancia según el tipo deseado
  • Agregue un editor personalizado que verifique si hay cambios en el campo de type y, si cambia, cree una nueva instancia con el método anterior y asígnela al campo de data

En total, esto le da este tipo de resultado:

gif de uso de ejemplo

 [CreateAssetMenu(fileName = "Data", menuName = "Inventory/Item", order = 1)] public class ItemObject : ScriptableObject { [CustomEditor(typeof(ItemObject))] public class ItemObjectInspector : Editor { SerializedProperty m_type; SerializedProperty m_data; private void OnEnable() { m_type = serializedObject.FindProperty("type"); m_data = serializedObject.FindProperty("data"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(m_type); if (EditorGUI.EndChangeCheck()) { m_data.managedReferenceValue = ItemObject.CreateBlankData((ItemType)m_type.intValue); } // avoid drawing type a second time // avoid drawing annoying Script field DrawPropertiesExcluding(serializedObject, new string[] { "type", "m_Script" }); serializedObject.ApplyModifiedProperties(); } } [System.Serializable] public enum ItemType { Physical, Magical } // Determines how to create an Item from each ItemType public static Item CreateBlankData(ItemType type) { switch (type) { default: case ItemType.Physical: return new PhysicalItem(); case ItemType.Magical: return new MagicalItem(); } } [System.Serializable] public class Item { [SerializeField] public string typeDescription; } [System.Serializable] public class MagicalItem : Item { [SerializeField] string elementName; public MagicalItem() { typeDescription = "Magical"; elementName = "fire"; } } [System.Serializable] public class PhysicalItem : Item { [SerializeField] float materialHardness; public PhysicalItem() { typeDescription = "Physical"; materialHardness = 1f; } } public ItemType type; [SerializeReference] public Item data; }

Nota: todas las clases anteriores son solo clases internas en aras de la brevedad. Pueden ser clases separadas o clases internas sin problemas.

over 4 years ago · Santiago Trujillo Relatório

0

Solo como una adición a la buena respuesta de Ruzihm .

Para este tipo de cosas, podría omitir la sobrecarga de implementar un editor personalizado y simplemente usar OnValidate

Esta función se llama cuando se carga el script o se cambia un valor en el Inspector (solo se llama en el editor).

Así que simplemente por ejemplo

 private void OnValidate() { switch(type) { case ItemType.Magical: // To avoid losing already filled in data // simply check if the current data already has the correct type if(data != null && data.GetType != typeof(MagicalItem)) { data = new MagicalItem(); } break; case ItemType.Physical: default: if(data != null && data.GetType != typeof(PhysicalItem)) { data = new PhysicalItem(); } break; } }
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda