How to show predefined structs in the entity inspector during runtime

I want to show the values of a struct contained in an IComponentData struct which I have defined. But the struct to show is a predefined struct from a Unity package which cannot be changed therefore. The entity inspector looks like this.

8943315--1226997--upload_2023-4-12_14-20-9.png

The endpoint is already expanded but empty. The code of the component shown:

  [Serializable]
  public struct GameSessionDefinition : IComponentData
  {
    public NetworkingMode NetworkingMode;
    public Unity.Networking.Transport.NetworkEndpoint Endpoint;
    public bool IsRenderingSuppressed;
  }

As mentioned the NetworkEndpoint struct cannot be modified. It has neither a serialized attribute nor public fields. Looks like this (stripped):

namespace Unity.Networking.Transport
{
    [StructLayout(LayoutKind.Sequential)]
    public unsafe struct NetworkEndpoint : IEquatable<NetworkEndpoint>
    {
        enum AddressType { Any = 0, Loopback = 1 }
        /* ... */
        internal Binding.Baselib_NetworkAddress rawNetworkAddress;
        /* ... */
        public ushort Port
        {
            get => (ushort)(rawNetworkAddress.port1 | (rawNetworkAddress.port0 << 8));
            set
            {
                rawNetworkAddress.port0 = (byte)((value >> 8) & 0xff);
                rawNetworkAddress.port1 = (byte)(value & 0xff);
            }
        }
        /* ... */
        public NetworkFamily Family
        {
            get => FromBaselibFamily((Binding.Baselib_NetworkAddress_Family)rawNetworkAddress.family);
            set => rawNetworkAddress.family = (byte)ToBaselibFamily(value);
        }
        /* ... */
        public string Address => ToString();
        /* ... */
        public override string ToString()
        {
            return ToFixedString().ToString();
        }
        /* ... */
        public FixedString128Bytes ToFixedString()
        {
            return AddressToString(ref rawNetworkAddress);
        }
        /* ... */
    }
}

I used a method mentioned in a differnt thread relying on Inspector<> and PropertyInspector<> from the Unity package “com.unity.properties.ui” but with no success. The code is not even called.

  public class NetworkEndpointPropertyInspector :  Unity.Properties.UI.PropertyInspector<Unity.Networking.Transport.NetworkEndpoint>
  {
    private TextField field;
    public override VisualElement Build()
    {
      this.field = new TextField(this.DisplayName) { value = this.Target.ToString() };
      return this.field;
    }
    public override void Update()
    {
      this.field.SetValueWithoutNotify(this.Target.ToString());
    }
  }
  public class NetworkEndpointInspector :  Unity.Properties.UI.Inspector<Unity.Networking.Transport.NetworkEndpoint>
  {
    private TextField field;
    public override VisualElement Build()
    {
      this.field = new TextField(DisplayName) { value = this.Target.ToString() };
      return this.field;
    }
    public override void Update()
    {
      this.field.SetValueWithoutNotify(this.Target.ToString());
    }
  }

Any ideas to get it work?

I don’t think Entity inspector window currently supports custom UI Elements inspectors;

You could try making PropertyDrawer for that specific property, though I’m not sure if they’re called either.
Otherwise only serializable fields can be displayed.

As a temporary workaround, you could make a separate debug data struct & attach it to the entity to display required data in editor only. Messy, but works.

I tried this. Unfortunately also didn’t worked.

Yep, this would be the only solution then. I think I make my own “CustomNetworkEndpoint” and map it to the Unity NetworkEndpoint when required. Then at least the ComponentData struct has the data only once.

You’ll need to setup internal access to Unity.Entities.UI
Then you can write custom inspectors via implementing PropertyInspector

Do you have any code samples or links showing the setup?

https://gitlab.com/tertle/com.bovinelabs.core/-/blob/master/BovineLabs.Core.Editor/Inspectors/ColliderInspector.cs

My BlobAssetReference inspector as a sample

3 Likes

Thanks for sharing the link. Unfortunately I did not got the PropertyInspector to work. But I found a quite simple solution which I like to share. With using the attributes

  • Unity.Properties.CreatePropertyAttribute
  • Unity.Properties.DontCreatePropertyAttribute

I achieved the desired display. In the Entity Inspector it looks like this now:
8956941--1230057--upload_2023-4-18_14-48-53.png

And that is the code of the component data struct:

  using Unity.Entities;
  using Unity.Networking.Transport;
  using Unity.Properties;

  public struct GameSessionDefinition : IComponentData
  {
    private struct DisplayEndpoint
    {
      public string Address;
      public ushort Port;
    }
 
    public bool IsRenderingSuppressed;
    public NetworkingMode NetworkingMode;

    [DontCreateProperty]
    public NetworkEndpoint Endpoint;

    [CreateProperty]
    private DisplayEndpoint endpoint // According to C# naming conventions the propery name should be capitalized but then a different name would be required
    {
      get
      {
        // Address includes port
        var address = this.Endpoint.Address;
        var hostname = address.Substring(0, address.IndexOf(':'));
        return new() { Address = hostname, Port = this.Endpoint.Port };
      }
      set => this.Endpoint = NetworkEndpoint.Parse(value.Address, value.Port);
    }
  }
2 Likes