Entity & GameObject Associations

Hi all,

I’m pondering some Entity + GameObject integration for things where the ECS approach is a little lacking, or where there are already some very developed GameObject/MonoBehavior systems but ECS would be beneficial for another system. But also I’m mostly just thinking about this to play around with things.

Associating an Entity with a GameObject is very straightforward. You just need a field. Associating a GameObject with an Entity is a little more involved. I see two easy ways.

1) Create a component class that inherits from IComponentData that contains a field for a GameObject. I haven’t seen this fully documented, but I found it in the threads here (thanks peeps). The ChangeLog suggests what we might suspect. Using an IComponentData class “allows managed types such as GameObjects or List<>s to be stored in components. Users should use managed components sparingly in production code when possible as these components cannot be used by the Job System or archetype chunk storage and thus will be significantly slower to work with. Refer to the documentation for component data for more details on managed component use, implications and prevention.”

2) Use EntityManager.AddComponentObject to add a GameObject to an Entity. The GameObject can be removed with RemoveComponent. As far as I can tell, there is not a command buffer equivalent (you can add the GameObject, but I’m not sure how to set it). The documentation notes that “Accessing data in a managed object forfeits many opportunities for increased performance. Adding managed objects to an entity should be avoided or used sparingly.”

3) A third option I have seen on these forums and elsewhere is to keep a central storage of GameObjects, and simple give an Entity a Component with an index to its associated GameObject, or to use use the Entity as a key to retrieve the GameObject.

From what I can tell, these first two methods seem to be equivalent. I believe the Entity with the components still function as normal in a Chunk, but anything done with the GameObjects themselves will naturally be slower. Of these two preference here would be 1) the component class, simply because it seems to be more flexible.

I think that method 3) would also perform similarly. The ECS parts of the code should be efficient, and then anything that needs the GameObject with have limitations. Depending on use, I could see this method having some benefits in reducing Entity Archetype changes. For example, if GameObjects are stored in an array, a IComponentData int with a value of -1 could indicate no associated GameObject, while any other value would indicate the position in the array. Similarly, If Entities were used as keys for GameObjects, it would be easy to associate, or not associate, an Entity with a game object without any Archetype change. I could see this approach being nice in some cases.

I’m curious what general thoughts you all might have.

FYI, you can use IConvertGameObjectToEntity and conversionSystem.AddHybridComponent(comp);
A CompanionLink will be created. with the function you described.

Also, all UnityEngine.Object is directly considered ManagedComponentData and can be added to entity as IComponentData.
But to use them the safe way, conversionSystem.AddHybridComponent(comp) is better.

1 Like

Interesting, I didn’t realize you could just add managed data directly. I think the method of adding GameObject as IComponentData is equivalent to method 1) and 2), but I’m not sure how to change the value once the GameObject is added.

I’ve seen the conversion system used to initialize an entity from a GameObject, but I’ve not seen it used to add a GameObject to an entity. I’m not sure if what you are suggesting is just the standard conversion process or something else.

WithOutBurst() and Run() on Entities.ForEach() will alow you to work on UnityEngine.Object.
As Burst doesn’t work on any managed data, and most GO/Component functions need to run in mainthread.

But I will not add a GameObject directly. conversionSystem.AddHybridComponent(comp) will give the entity a ManagedComponentData of the target comp type.
It’s done by clone the converted GameObject remove all none-HybridComponent. Add a CompanionLink of that go clone to the converted entity. And add all HybridComponent on the clone to the converted entity. the clone is hidden from hierarchy inspector. And the clone’s transform is synced with the entity every frame.
So it’s most of the thing I would expect.
conversionSystem.AddHybridComponent(comp) is the standard way.(component instead of gameobject)
One flaw is the parent/child hierarchy is lost(transform value work as the entity will have proper Parent/Child hierarchy, but GetChild from Transform will not work), and all UnityEngine.Object reference would be lost as the original GameObject is deleted.