Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Combine ECS and Monobehavior on same object?

Discussion in 'Entity Component System' started by Kyle45, Jul 3, 2023.

  1. Kyle45

    Kyle45

    Joined:
    Apr 18, 2015
    Posts:
    10
    Hi,

    I was wondering what the best way is to combine monobehavior components and ECS components on the same object? For example, I'd like to attach authoring components to a gameobject and have them be converted to ECS components on an entity automatically at runtime, instead of converting an entire gameobject to an entity through the use of sub-scenes.

    Thanks for the help!
     
    Last edited: Jul 4, 2023
  2. Walley7

    Walley7

    Joined:
    Dec 4, 2019
    Posts:
    54
    The way I'm currently handling this is to have the objects start off as entities, associate them with a gameobject prefab, and instantiate that prefab and link the two together.

    A simple way to do this is to have a prefab managed component on the entity, which holds a reference to a GameObject prefab and a GameObject instance, and on the spawned GameObject I have an EntityLink monobehavior which holds a reference to the entity.

    This looks roughly as follows:
    Code (CSharp):
    1. public class CPrefab : IComponentData {
    2.     public GameObject prefab;
    3.     public GameObject instance;
    4. }
    5.  
    6. public class PrefabAuthoring : MonoBehavior {
    7.     public GameObject prefab;
    8.     public class Baker : Baker<PrefabAuthoring> {
    9.         public override void Bake(PrefabAuthoring authoring) {
    10.             Entity entity = GetEntity(TransformUsageFlags.Dynamic);
    11.             AddComponentObject(entity, new CPrefab() { prefab = authoring.prefab });
    12.         }
    13.     }
    14. }
    15.  
    16. public partial struct HybridSystem : ISystem {
    17.     public void OnUpdate(ref SystemState state) {
    18.         foreach ((CPrefab p, Entity e) in SystemAPI.Query<CPrefab>().WithEntityAccess()) {
    19.             p.instance = GameObject.Instantiate(p.prefab);
    20.             p.instance.GetComponent<EntityLink>().entity = e;
    21.         }
    22.     }
    23. }
    24.  
    25. public class EntityLink : MonoBehavior {
    26.     public Entity entity;
    27. }
    There's a number of extra steps you can take here, such as feeding LocalToWorld.Position and LocalToWorld.Rotation into the game object's transform, having another system which keeps the transforms in sync, or storing the instance in a separate component if you want your systems to be able to specifically query for that.

    But basically the above opens the door to hybrid entities.

    P.S. You also have to be mindful about when the systems run - for instantiation I've found the end of InitializationSystemGroup to be the most sensible.
     
    apkdev, Ozzieme, Kyle45 and 1 other person like this.
  3. Kyle45

    Kyle45

    Joined:
    Apr 18, 2015
    Posts:
    10
    Ok seems a bit more complicated than the previous versions of ECS, but thank you for the answer!