Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

ComponentData Properties in Inspector

Discussion in 'Entity Component System' started by JooleanLogic, May 15, 2018.

  1. JooleanLogic

    JooleanLogic

    Joined:
    Mar 1, 2018
    Posts:
    447
    I don't know if I've missed something obvious or if others have a solution on how to get ComponentData properties in the inspector? I can't see much on it in the forums.
    I use the below reflection method which seems to work now but was completely crashing Unity initially. Don't know why. I'm a noob in C# so if there's a better way, I'm all ears.
    I just extend from the ComponentWrapper class below instead of Unity.Entities.ComponentDataWrapper and then add matching variables in the wrapper subclass for what you want to show in the Inspector.

    ComponentWrapper.cs
    Code (CSharp):
    1. using System;
    2. using System.Reflection;
    3. using UnityEngine;
    4. using Unity.Entities;
    5.  
    6. public class ComponentWrapper<T> : ComponentDataWrapper<T> where T : struct, IComponentData
    7. {
    8.     private void Start()
    9.     {
    10.         const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
    11.  
    12.         var component = getDataComponent();
    13.         object boxed = component;
    14.  
    15.         Type componentType = component.GetType();
    16.         FieldInfo[] wrapperFields = this.GetType().GetFields(flags);
    17.         foreach (FieldInfo wrapperField in wrapperFields)
    18.         {
    19.             FieldInfo componentField = componentType.GetField(wrapperField.Name);
    20.             if (componentField != null)
    21.             {
    22.                 try
    23.                 {
    24.                     if(wrapperField.FieldType == typeof(GameObjectEntity))
    25.                     {
    26.                         GameObjectEntity go = (GameObjectEntity)wrapperField.GetValue(this);
    27.                         componentField.SetValue(boxed, go.Entity);
    28.                     }
    29.                     else
    30.                     {
    31.                         componentField.SetValue(boxed, wrapperField.GetValue(this));
    32.                     }
    33.                 }catch(Exception e)
    34.                 {
    35.                     Debug.LogError(e.Message);
    36.                 }
    37.             }
    38.             else
    39.             {
    40.                 Debug.LogError("Warning: ComponentWrapper Field " + wrapperField.Name + " was not found in ComponentData type " + componentType.Name);
    41.             }
    42.         }
    43.  
    44.         component = (dynamic)boxed;
    45.         setDataComponent(component);
    46.     }
    47.  
    48.     private T getDataComponent()
    49.     {
    50.         Entity entity = gameObject.GetComponent<GameObjectEntity>().Entity;
    51.         return World.Active.GetOrCreateManager<EntityManager>().GetComponentData<T>(entity);
    52.     }
    53.  
    54.     private void setDataComponent(T t)
    55.     {
    56.         Entity entity = gameObject.GetComponent<GameObjectEntity>().Entity;
    57.         World.Active.GetOrCreateManager<EntityManager>().SetComponentData<T>(entity, t);
    58.     }
    59. }

    And in the Component class file go:
    MyComponentWrapper.cs
    Code (CSharp):
    1. public struct MyComponent : IComponentData{
    2.     public Entity parent;
    3.     public float capacity;
    4.     public float amount;
    5. }
    6.  
    7.  
    8. public class MyComponentWrapper : ComponentWrapper<MyComponent> {
    9.     // Variables in here must match same name as component above.
    10.     public GameObjectEntity parent;
    11.     public float capacity;
    12. }
     
  2. RaL

    RaL

    Joined:
    Nov 29, 2013
    Posts:
    35
    I just use the [Serializable] attribute

    Code (CSharp):
    1. [Serializable]
    2. public struct MyComponentData : IComponentData
    3. {
    4.     public float Value1;
    5.     public float3 Value2;
    6. }
    7.  
    8. public class MyComponentDataWrapper : ComponentDataWrapper<MyComponentData> {}
     
  3. JooleanLogic

    JooleanLogic

    Joined:
    Mar 1, 2018
    Posts:
    447
    Lol. That could've saved me a couple of hours.
    Does it work for an Entity field? It's not showing up in mine.