Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

443
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda