Search Unity

New SubScene & ConvertToEntity workflows

Discussion in 'Data Oriented Technology Stack' started by Joachim_Ante, Mar 4, 2019.

  1. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    329
    @Opeth001

    It would also seem that using both systems at the same time is very problematic. Since in your case both the proxy and conversion system seem to be trying to add the same component type to a single entity, which is not allowed and leading to that error.
     
  2. addent

    addent

    Joined:
    Apr 27, 2019
    Posts:
    14
    Thanks, I've given this a try on a small test scene and it works. I'll have to try it on my bigger hierarchy in the near future.

    In the meantime, what I ended up doing was just to have a hierarchy of normal GameObjects and another completely separate hierarchy of entities. Then I have a two component systems to keep them in sync: one that runs before any other system to copy data from the gameobject onto the entities, then a second that runs after the other component systems copy the entity data back onto the gameobjects. Its kind of a crap solution, but at least I don't have to rewrite a bunch of my monobehaviour scripts to make them work in ECS.

    I still don't know why they don't let us use the 'Convert and Inject Game Object' on both parent and child objects in the same hierarchy. It feels like that would make things easier.
     
  3. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    329
    @addent Don't know if this is of any help on the matter but when creating a new "Authoring Component Type" script from the create menu it includes this note:
    Not sure why this is recommended or if it applies to child object management though.
     
  4. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    329
    Checking out the Unity Physics package code, docs and samples is very helpful here since that system uses the conversion system extensively. By just looking through the Getting Started section of the manual I was able to learn that you could use the conversion utility class to convert the GameObject and children without even attaching a ConvertToEntity Script at all.

    Code (CSharp):
    1. using Unity.Entities;
    2. using UnityEngine;
    3.  
    4. public class ConversionScript : MonoBehaviour
    5. {
    6.     void Start()
    7.     {
    8.         GameObjectConversionUtility.ConvertGameObjectHierarchy(gameObject, World.Active);
    9.     }
    10. }
    Update: It seems the above code doesn't work for hybrid setups because it doesn't preserve and inject the original GameObject, and this is probably why it's giving me null reference exceptions whenever I try it.

    Perhaps they could add a conversion mode flag or entirely new utility function so we can convert and inject the whole object through code. But for now it seems easiest to just keep using the old GameObjectEntity/Proxy for any children you'd like to convert and inject.

    cc: @thelebaron
     
    Last edited: Jul 16, 2019
    addent likes this.
  5. addent

    addent

    Joined:
    Apr 27, 2019
    Posts:
    14
    Thanks for the info. I have not touched the ECS physics example yet, but a cursory glance shows that I definitely need to dig through it to get a better understanding of this stuff.
     
  6. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    87
    It's referring to CreateAdditionalEntity method. You can use inside a GameObjectConversionSystem or IConvertGameObjectToEntity.Convert method:

    Code (CSharp):
    1. public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) {
    2.     var childEntity = conversionSystem.CreateAdditionalEntity(child);
    3.  
    4.     // ...
    5. }
    It's just the recommended way instead of calling dstManager.CreateEntity directly.

    []'s
     
    IsaiahKelly likes this.
  7. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    329
    What's the best way to get the entity associated with a converted GameObject? In the old system you could just do:
    Code (CSharp):
    1. gameObject.GetComponent<GameObjectEntity>().Entity
    The ConvertToEntity class has no such reference to the entity, as far as I know.
     
    Opeth001 likes this.
  8. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    87
    You need to store yourself.
    Code (CSharp):
    1. public class EntityReference : MonoBehaviour, IConvertGameObjectToEntity {
    2.     public Entity Entity { get; private set; }
    3.     public World World { get; private set; }
    4.  
    5.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem) {
    6.         Entity = entity;
    7.         World = dstManager.World;
    8.     }
    9. }
    * I'm on mobile so the code certainly has some typo.

    []'s
     
    addent and IsaiahKelly like this.
  9. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    329
    That's what I suspected. Thanks.

    This method seems to be the key to converting select child objects to entities with the new conversion system. However, I still don't understand how to use it properly. If I call CreateAdditionalEntity in the parent script, passing it the child object, it gives me the error:
    But I have no idea where or when I should be calling GetPrimaryEntity or what needs the reference. I tried calling it right before CreateAdditionalEntity, which gives me the error:
    I can fix this error by implementing IDeclareReferencedPrefabs but than I just get the original error again.
     
  10. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    329
    I'm somewhat confused now.

    When I try adding GameObjectEntity to a child object I get the warning message:
    This strongly suggest that all children are supposed to be converted along with the parent. But this obviously isn't happening. Only the components attached to the parent/root GameObject are included in the conversion process (unless you use ConvertGameObjectHierarchy, which still doesn't work with injection). So I'm guessing this is now a bug.
     
  11. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    87
    When calling CreateAdditionalEntity you must pass a parameter that already has a "Primary Entity". In Inject Mode, only one entity will be created, the first one with ConvertToEntity in the hierarchy.
    So you need create a additional entity based on this entity and add any other component manually, including parent/child relationship.
    To make an entity to be a child of another, you need to add Parent and LocalToParent components.

    EntityManager has a method called SetName that can help when you want to find a specific entity in Entity Debugger.

    []'s
     
    IsaiahKelly likes this.
  12. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    329
    @elcionap Thank you for all the info but I still don't really understand this system.

    I actually just want to create an additional entity with the conversion system from a child object, just like the parent. I don't actually need or care about the entity parent/child relationship here. The issue is that placing a ConvertToEntity script on the child does nothing because the root ConvertToEntity script cancels it out. However, the warning messages seem to suggest that the system should at least convert all IConvertGameObjectToEntity scripts in the GameObject hierarchy to the primary entity but this isn't happening. And even using ConvertGameObjectHierarchy seems to only convert the transforms and none of the child IConvertGameObjectToEntity scripts.

    The only solution I can think of right now is to separate the child into a prefab and instantiate it at run instead so the ConvertToEntity script attached to it actually runs, but this feels like a lot of work for such a simple objective and makes me want to go back to the old GameObjectEntity system.
     
  13. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    261
    @IsaiahKelly You only need the one ConvertToEntity script in your hierarchy, and you handle referenced GameObjects via whatever script implements IConvertGameObjectToEntity. I posted a snippet near the top of this page but to further elaborate:
    Code (CSharp):
    1. public class MyBehaviourAuthoring : MonoBehaviour, IConvertGameObjectToEntity
    2. {
    3.     public GameObject ChildWeapon; // A child in this gameObject's hierarchy
    4.  
    5.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    6.     {
    7.         // - Add the immediate components the parent needs
    8.         dstManager.AddComponentData(entity, new Health());
    9.         dstManager.AddComponentData(entity, new CopyTransformFromGameObject()); // Or CopyTransformToGameObject - Only if you need to sync transforms
    10.         // I believe that translation, localtoworld and rotation are automatically added to the root object that has the ConvertToEntity with Inject selected
    11.      
    12.         // - Create an entity for the PlayerWeapon gameObject and add components manually
    13.         var weaponEntity = dstManager.CreateEntity();
    14.         dstManager.AddComponentObject(weaponEntity, ChildWeapon.transform); // Add child transform manually
    15.         dstManager.AddComponentData(weaponEntity, new Translation()); // Have to add all this stuff manually too
    16.         dstManager.AddComponentData(weaponEntity, new Rotation());
    17.         dstManager.AddComponentData(weaponEntity, new LocalToWorld());
    18.         dstManager.AddComponentData(weaponEntity, new CopyTransformFromGameObject()); // Or CopyTransformToGameObject - Only if you need to sync transforms
    19.      
    20.         // - Only if you want the parent child relationship
    21.         dstManager.AddComponentData(weaponEntity, new Parent{Value = entity});
    22.         dstManager.AddComponentData(weaponEntity, new LocalToParent());
    23.     }
    24. }
    I admit I don't remember if I tried what you posted above, as this has been working for me and in lieu of any official statement regarding the proper conversion of a hierarchy, I'll just be sticking with this for now.
     
  14. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    329
    @thelebaron I know you can do this all manually but that defeats the whole purpose of the conversion system. I also see you've been able to convert child objects before in a previous version. That and the warning messages I've received make be believe/hope this must be some kind of bug or oversight. Surely there must be a way to use IConvertGameObjectToEntity on child objects too. And if not there should be! Perhaps we just need some actual documentation on how to do this.
     
    Last edited: Jul 19, 2019
    Sonorpearl likes this.
  15. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    261
    Oh my bad. Yeah an automated workflow would be nice. Also an automatic conversion of a hierarchy and child colliders without merging them into a mega collider would be really nice for animated characters, along with better joint authoring workflows.
     
  16. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    329
    Yeah, I believe this is the ultimate goal and Unity physics actually already automatically converts PhysX colliders for you with the conversion system. I also remember someone from Unity saying you should eventually be able to edit a bunch of transforms on a character in the editor and have them all converted at run-time for best performance, etc.
     
  17. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    87
    Did you tried ConvertToEntity.ConvertAndInjectOriginal static method? Unfortunately the method doesn't return the created entity but something like the EntityReference example above can be used for this.

    I haven't tried the code but looking in the sources should work properly.

    []'s
     
  18. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    329
    @elcionap ConvertAndInjectOriginal is actually what is called when you set conversion mode to "Convert And Inject Game Object" so that doesn't change anything unfortunately:

    Code (CSharp):
    1.         void Awake()
    2.         {
    3.             if (World.Active != null)
    4.             {
    5.                 // Root ConvertToEntity is responsible for converting the whole hierarchy
    6.                 if (transform.parent != null && transform.parent.GetComponentInParent<ConvertToEntity>() != null)
    7.                     return;
    8.              
    9.                 if (ConversionMode == Mode.ConvertAndDestroy)
    10.                     ConvertHierarchy(gameObject);
    11.                 else
    12.                     ConvertAndInjectOriginal(gameObject);
    13.             }
    14.             else
    15.             {
    16.                 UnityEngine.Debug.LogWarning("ConvertEntity failed because there was no Active World", this);
    17.             }
    18.         }
    However, the comment here is helpful because it again says it should be converting the whole hierarchy, which it isn't.
     
  19. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    710
    I'd like to create a SubScene and transfer a procedural generated prefab into the SubScene by script.
    This is possible by the content of
    class SubSceneContextMenu


    If a SubScene is created already I'd like to got the complete prefabs by transform and gameobjects.
    But SubScene.GetComponentsInChilderen<transform> does not return the complete content.

    A workaround would be to move the game objects out of the SubScene + rework, than rebuild the SubScene again. But nothing works in this case. Would love to have SubScene.GetContent(); or similar.

    Does any one know how to read through the game objects in a SubScene and/or remove perhaps?

    Thank you!
     
  20. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    710
    #### IsChildOf BUG ? #####

    I'm using an editor window.
    If the SubScene is open for edit then AnyGameObject.IsChildOf(SubScene.gameObject.transform) return always false for any game-object is inside the SubScene. Normally should be true.

    Code (CSharp):
    1. using Unity.Scenes;
    2. public SubScene subScene;
    3. public GameObject anyGO;
    4. Debug.Log(anyGO.IsChildOf(subScene.transform));
     
  21. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,560
    Could be wrong on this one, but I suspect that isn't a bug. I don't think root objects in a scene have a parent - even if it's a subscene. However you could consider it unexpected behaviour.
     
  22. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    710
    Yes that true on a real scene and it has no transform in inspector. A SubScene has a transform component.
    1) Now there is no way to determine what objects containing a SubScene I guess.

    2) Another issue with the SceneManager. If a SubScene is closed, the SceneManager does not list the SubScene. At runtime it's not possible to find and load a SubScene.

    And there are other issues with SubScene, when editing prefabs in Hlod.cs, duplicating and insert SubScenes. It really requires a hands on.

    Code (CSharp):
    1.           using UnityEngine.SceneManagement;
    2.             Scene[] Scenes = new Scene[SceneManager.sceneCount];
    3.             for (int i = 0; i < SceneManager.sceneCount; i++) {
    4.                 Scenes[i] = SceneManager.GetSceneAt(i);
    5.                 Debug.Log(Scenes[i].name);
    6.             }
    7.  
     
    Last edited: Jul 22, 2019
  23. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,560
    1. Except it doesn't really. If you make changes to the SubScene transform it does not affect the scene transforms (and even warns this.)

    upload_2019-7-22_11-21-20.png

    I always imaged subscenes were designed to really just be 1 scene that you've broken into parts. It should work exactly the same if all the subscenes were just a single scen and entities shouldn't really care if they are part of a subscene or not.

    If you want them at runtime separate, you can just load a scene of entities classically with
    SceneManager.LoadSceneAsync, You don't have to use a subscene.

    Anyway really just my interpretation. I suspect they'll be fleshed out a lot more in the future making them more versatile.
     
    Last edited: Jul 22, 2019
  24. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    710
    A warning is not an argument to block a required feature. Isachild of should definetely return true on the subscene has a transform attached. This is a required technical solution.for a minimum workflow. Or, did you have a solution to list the gameobjects of a SubScene?

    The scenemanager doesnt know about a closed subscene.
     
  25. PublicEnumE

    PublicEnumE

    Joined:
    Feb 3, 2019
    Posts:
    76
    Does the Conversion of a hierarchy happen in a reliable order?

    For example, are parent GameObjects always converted before their children?
     
  26. diesoftgames

    diesoftgames

    Joined:
    Nov 27, 2018
    Posts:
    28
    I didn't see any responses to this question. I'm running into what sounds to be the same kind of hybrid situation, but now I'm wanting to create a custom world and I'm not finding any way to achieve that. It would be very easy for me to get a reference to world in question into an IConvertGameObjectToEntity MonoBehaviour, but I'm not sure what I would even do with it from there to "move" the entity over to that world.

    UPDATE: fwiw I tried setting World.Active to my custom world, but I can't seem to make that happen before the conversion happens, so I see the IConvertGameObjectToEntity method called on my hybrid objects before my MonoBehaviour (which I have set to extremely high negative priority) gets a chance to create the custom world.
     
    Last edited: Aug 4, 2019
  27. Opeth001

    Opeth001

    Joined:
    Jan 28, 2017
    Posts:
    232
    is there plans to add Baked shadows and lights to Subscenes soon ?
     
    Kender and thelebaron like this.
  28. ben_unity9

    ben_unity9

    Joined:
    Sep 21, 2017
    Posts:
    5
    @Joachim_Ante , sorry if I am asking a question you already answered, I can't seem to find the answer anywhere, but: what are the plans for baking support? We're working on a project that uses the "New SubScene & ConvertToEntity workflows" and it requires us baking lights. I am not too sure what the alternatives could be in the meantime.
    Thanks!
     
  29. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    243
    All of the link in github is broken. Should changed URL from
    ../Samples/..
    to
    ../ECSSamples/..
     
    justaguygames likes this.
  30. justaguygames

    justaguygames

    Joined:
    Mar 4, 2015
    Posts:
    9
    What is the best way to create an entity from a gameobject while being able to reference components like rigidbody from the editor? I got it to work by placing a converttoentity component where I chose inject game object. But then I seem to have the original object lying around in the scene (which makes sense because it was in the scene to begin with). Should I create a prefab and load that, or can you make an entity from a gameobject in the scene, without duplicating it AND have the entity retain the rigidbody component?
     
  31. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    329
    @scotthNM @Opeth001 @ben_unity9

     
  32. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    329
    I don't think you understand how the conversion system works. Classic GameObject components can not be directly added to an entity, they can only linked to the entity from a GameObject. So the original GameObject must still exist if you want to have any classic components associated with the entity. The "inject GameObject" conversion option does exactly this by not destroying the GameObject after conversion, so you can still access it's components.

    This also means you need to keep related values in sync between the entity and GameObject. So for something that affects translation like a rigidbody, you need to keep the GameObject and associated entity translation in sync using something like the CopyTransformFromGameObject component or your own custom sync system.
     
    justaguygames likes this.
  33. diesoftgames

    diesoftgames

    Joined:
    Nov 27, 2018
    Posts:
    28
    Is there a best practice for instantiating hybrid prefabs at runtime after the initial scene load? It takes a very long time (in excess of 17ms) to instantiate GameObjects that have a Convert-and-inject conversion component attached to them. Most of that time is spent in GameObjectConversionUtility.CreateConversionWorld(), with a decent amount of time also spent in GameObjectConversionUtility.Convert(). Is there any way to hold onto a conversion world for reuse since I know I'll occasionally be needing it to instantiate hybrid prefabs?
     
    Sonorpearl likes this.
  34. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    44
    RectTransform conversion is finally fixed. I started rewriting my UI system to ConvertToEntity workflow but quickly encountered another problem. Editor (2019.3.0a11) crashes even with very simple RectTransform hierarchies. I already reported the issue (1175841) with simple reproduction project. I hope you can fix it in a reasonable time because it's blocking my UI development.
     
  35. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    4,641
    Does it also happen in 19.1? Most of our daily testing still happens on 19.1.
     
  36. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    44
    Yes. I tested it on 2019.1.14f1 and it crashed too. Unfortunately, no crash report or stack trace. Editor log stops here:
     
  37. ZoeyDove

    ZoeyDove

    Joined:
    Nov 12, 2018
    Posts:
    10
    Hello!

    Is there a way for a conversion system to "hide" components from other conversion systems?

    I'm mapping out camera boundaries in ProBuilder, but I don't want the meshes converted, or even the transform really.

    My CameraBoundaryConverter will look for game objects with the CameraBoundary component and create a correctly filtered physics collider. I would like that same system to also prevent other conversion systems from running on that object - either all of them, or I specify components to "hide" from other converters (like transform and mesh filter).

    Thanks~