ECS with world-space UI - HybridComponents vs Convert & Inject

Hi, I need some help instantiating world-space UIs with ECS. I spawn some NPCs that sometimes have to display text information, health bars and buttons above their heads. As we cannot use UI Elements yet, the only option seems to be a hybrid approach with the old UI system.

So far I have tried:

a) HybridComponents

My tests have made me believe, that this currently does not work for hierarchies of GameObjects and their components, if these components depend on components of their ancestors. So if I have a parent GameObject with a canvas and a child GameObject with a button, I can register both components in the conversion process as hybrid components, but after conversion this results in two independent hidden GameObjects with these components that are not in a parent-child relationship. Or is that wrong? Maybe something else is the problem, but I do see all the necessary components on the hidden GameObjects in the inspector, i just do not see any UI in the GameView.

I would like to use HybridComponents as I would not have to take care of the hidden GameObjects they are linked to. But this does not seem to be possible at the moment. Or am I doing something wrong?

b) Convert & Inject

The following method does seem to work, but requires me to take care of the linked GameObjects which is cumbersome:

  • I use Addressables to load a GameObject prefab that is marked with “Convert & Inject”
  • I instantiate the prefab with GameObject.Instantiate
  • I use GameObjectConversionUtility.ConvertGameObjectHierarchy with the new instance to get an entity that is linked to the instantiated GameObject

This is probably quite slow as GameObjectConversionUtility is not intended for this use case. Also, if I delete the entity, the linked GameObject is not deleted as well, which adds another complication.

I have also read this thread that describes a similar “manual” method of instantiating an entity prefab that is linked to a GameObject, but it seems very complicated to me.

Are there any other options?

Associating an Entity with the GameObject:
Create a MonoBehaviour. In its awake method, grab the default world’s EntityManager and create an entity. Then add the MonoBehaviour to the entity using AddComponentObject. Now by instantiating the prefab with this component, you get the MonoBehaviour associated with an entity that you can use in Entities.ForEach. You’ll have to manipulate its Transform GameObject style.
Making the GameObject auto-destruct when the Entity is deleted:
This one is a little trickier. Create a system which stores a List of your custom MonoBehaviour and a list of integers (the latter could be a NativeList if you feel like it). Create a register method which takes an instance of the MonoBehaviour and the Entity. The list of integers is a freelist, meaning if it contains a value, that value represents an index in your MonoBehaviour list that is free and that’s where the passed in MonoBehaviour should go. If the freelist is empty, add the MonoBehaviour to the back of the list. Create an ISystemStateComponentData which stores an int. In the system, add that component to the entity and assign the index the MonoBehaviour went into to the component. Also create a IComponentData tag and add it to the entity. Fetch this system in the Awake method of the MonoBehaviour and call it.
Now in the system’s OnUpdate, iterate through all entities which have the ISystemStateComponentData but not the IComponentData. Each value of ISystemStateComponentData represents an index into the MonoBehaviour list whose GameObject you need to destroy, and an index you need to add to the freelist.

3 Likes

Thanks for the help and the ingenious auto-destruct method! I also did not realize that I do not have to use the conversion workflow at all, that will reduce some complexity. I am really looking forward to the day the UI Toolkit (UI Elements) will work with ECS and in world space, but that is probably still a long time off.

Have a look at the new com.unity.ui package, they annonced on wednesday.
They have a demo project with world space health bars :

https://discussions.unity.com/t/799315

2 Likes

Thanks, I did miss that announcement. I will try to use UI Toolkit with ECS. Have you already tried to combine the two?

Are world space health bars really possible right now? In the announcement they are only talking about health bars in screen space that follow other game objects:

I don’t really need world space UIs, as long as the UI follows the NPCs correctly, so that’s probably fine for me.

1 Like

You are rigth it’s not realy world space, it’s more screen space but the ui follow the projection of the unity worldspace onto the screen and as far as I can see it also scale based on how far it is from the camera.

I did try to use it in my Ability system with DOTS and managed to synch entity data to the ui but the scaling of the display is bugged. I did a bug report that Unity team managed to reproduce so hopefully it will get fixed in next versions.

I suggest you download and open the sample they refrenced in the annoncment. It does not use DOTS but appart from where you get the data (Entity or monobehavior) it should be the same logic.

1 Like

Great! I will try that.

1 Like