Search Unity

Transform system custom integrations

Discussion in 'Entity Component System' started by snacktime, Apr 6, 2019.

  1. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    I'm curious is the transform system even meant to be used outside of convert to entity flow?

    For one I would prefer to not be forced to use prefabs.

    Second, our use case is one where not all entities of the archetype in question have a transform.

    I tried doing it all via code. Used AddComponentObject to add a Transform, added LocalToWorld, Translation, and Rotation components, but nothing was being synced.
     
  2. Marius_L

    Marius_L

    Joined:
    Jan 16, 2016
    Posts:
    7
    Create a working parent-child relationship using prefabs, then check what archetype is created in the debugger. Add whichever components you see.
     
  3. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    That's not the issue. You can create the same components yourself and it doesn't work, there are other internal structures created to track stuff using the convert to entity flow. I want to know what the intent is, will there be public api's to handle this yourself at a lower level, or are we expected to just use IJobParallelForTransform directly when convert to entity doesn't fit the task.
     
  4. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    Fundamentally this is impossible. An archetype will either have classical Transform component or it won't. Transform is a type which constitutes the archetype.

    The only use case I could see where you would need to sync the entity's LocalToWorld to the GameObject's Transform and not use a prefab or a scene GameObject would be if you are procedurally generating a GameObject from scratch. In that case, can't you just add the ConvertToEntity component last and let you conversion world kick off in the newly created GameObject's Awake()?
     
  5. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    Sure at the entity level it will have a transform, but it could just be a pooled one and ignored. If the larger abstraction has a good reason to not have a transform in all cases,then special casing it in the ECS case makes the most sense. This is exactly what we do with our own transform syncing using IJobParallelForTransform directly.

    And what if you don't want a bunch of components pulled in from your prefab? You just want the transform? I didn't actually look far enough into convert to entity to see if you could specify an archetype and it only pulls in what you specify.

    But in any case why is convert to entity required just to use the transform system? Transforms are a special case, not just another monobehaviour. The transform system should be able to stand on it's own, I should be able to use it outside of any other concerns.
     
  6. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    ECS and GameObjects are two separate APIs with fundamentally different philosophies. There's the ECS transform system, the GameObject transform system, and some bridging logic to help aid some common workflows. The first two each stand on their own and are not related to each other. And they both work very well, but they are not designed to work together. There's some logic on the ECS side to allow GameObject components to be associated to an entity, but it gives no special treatment to any particular component in the same way GameObject API would. So in fact from the ECS's view, a Transform component really is just like any other MonoBehaviour.

    Anyways, I'm going to take another guess at your use case. If I'm wrong, you're going to have to be very specific about the problem you are trying to solve.

    I am guessing that you are mostly working in a GameObject architecture, but have some costly simulations that you not only want to jobify, but you want to use ECS for the nicer API. Thus you need a one-way reference from one API to reference data in the other. There's two ways you could go about it. You could either store the entity in some MonoBehaviour and schedule a job with a ComponentDataFromEntity and a NativeArray of TransformAccess. Or you could store the Transform component on the Entity and use Unity's premade systems to do the syncing. Those systems use these EntityQuerys to work:
    Code (CSharp):
    1. m_TransformGroup = GetEntityQuery(
    2.                 ComponentType.ReadOnly(typeof(CopyTransformFromGameObject)),
    3.                 typeof(UnityEngine.Transform),
    4.                 ComponentType.ReadWrite<LocalToWorld>());
    5.  
    6. m_TransformGroup = GetEntityQuery(ComponentType.ReadOnly(typeof(CopyTransformToGameObject)), ComponentType.ReadOnly<LocalToWorld>(), typeof(UnityEngine.Transform));
    So if you aren't satisfying those queries, that's your issue. Another workaround in case that doesn't resolve the issue for some odd reason is that you can run your own GameObjectConversionSystem that updates after all the other systems and finds all entities with some magic tag component and prunes them of all the components except the ones you care about.
     
  7. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    You don't need to explain the basics. I thought it was obvious from mentioning that we use IJobParallelForTransform directly that we know how to sync it all ourselves. We maintain our own TransformAccessArray. Using a similar flow to what Unity does internally for synchronizing in both directions.

    The question was is there a way to use the transform system without convert to entity. The transform system does not stand on it's own like you say as far as I can tell. Internally convert to entity seems to be what they use to create all the bindings needed (look at TransformConversion). The docs for the transform system also point at TransformConversion.

    If you just create the necessary components, none of them are written to by the transform system. If you use convert to entity on an otherwise empty GameObject, it will write to them. So there are other internal data structures that convert to entity is creating.
     
  8. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    To be clear, the goal isn't trying to find how to sync things. It's to find out if we can use the built in transform system. There are I think benefits to using what Unity created, but it has to make sense. If their flow creates more work for no real gain, it just doesn't make sense. In our case making sense would probably mean the transform system has api's just to handle transforms, not other concerns.
     
  9. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    The only bindings that Unity is using is that all the ICDs and the GameObject's Transform are attached to the entity. But just attaching the components isn't going to automatically update them to be in sync. You have to let the ECS transform systems run on them first. The TransformConversion will initialize all the ECS components to match the GameObject Transform, but it doesn't create any bindings. From your initial post, I'm suspicious you are missing the CopyTransformTo/FromGameObject components on your entity in order to make the queries grab your entities. I'd check the entity debugger to make sure your entities show up in those systems' queries.

    But also, Unity's built-in system sync code does not handle scale. So your system might already be better for you.
     
  10. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    It could very well be that I'm missing the right components, but the copy to/from components are not compatible with convert to entity, at least not if you just try to add them to a prefab that has convert to entity. They add the old GameObjectEntity and then convert to entity complains. So I assumed the copy to/from were also deprecated in favor of some new way of handling it.

    But a component based approach to syncing is problematic to start with. It assumes you need to sync everything every frame. It doesn't provide a way to be selective. I'm curious why for example they didn't just add another IComponentData component to their set of standardized transform components with fields to specify if the transform should be synchronized.
     
  11. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    That's your problem right there. You are adding the proxies. Not the actual ICDs. Add the actual copy to/from ICDs either at runtime or through a custom IConvertGameObjectToEntity if its a prefab.

    And you can control syncing by adding and removing the ICDs from your entities.
     
  12. JooleanLogic

    JooleanLogic

    Joined:
    Mar 1, 2018
    Posts:
    447
    This. They introduced a new mechanism that conflicts with the old without providing equivalent IConvertGameObjectToEntity proxies for their built in synch systems (copy from/to etc).
    As well 'Convert to Entity'->'Convert and Inject Game Object' doesn't convert Game Object hierarchies so it's a bit confusing from latest release what is their plan for hybrid ecs.
     
  13. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    ConvertToEntity class has static methods for conversion. Adding ConvertToEntity monobehavior it’s not required. You can get GO and call conversion at any time.