Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

ECS Hybrid: Copying Animation data back into ECS

Discussion in 'DOTS Animation' started by james7132, Aug 19, 2020.

  1. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    166
    One of the strict requirements of the project I'm experimenting with porting to ECS is deriving object positions based on animation-driven Transforms. Before this was simple as I could directly read the Transform positions. However, in ECS Hybrid, Entities drive the positions of Transforms, not the other way around. From here I've found several ideas on how to do this:
    • Use DOTS Animation to sample animation, copy data into Translation/Rotation/Scale on Entities, use hybrid links to write the results to the Transform components which drives the SkinnedMeshRenderer. (I still need cloth physics, which doesn't seem to be supported by both DOTS Animation and DOTS Physics do not support right now).
    • Use a custom job to sample a Playable on the main thread then use a separate job with a TransformAccessArray to copy this data back into their linked Entities. Compute the locations for the simulation objects, then use the hybrid link to write the same data back into Transforms.
    • Bake either at startup or at edit time the transform data for into a BlobAsset to skip runtime data sampling entirely and just read the per-game tick transform data from the BlobAsset. The associated GameObject only follows the animation sample rate as a view for the underlying simulation data.
    Until DOTS Animation is in a more usable state, what's the suggested way to approach this problem? Related to two of the ideas I've listed here, is are the TransformStream computations done in Animation Jobs or Playables computed with FloatMode.Strict or FloatMode.Fast? Determinism is one of the big reasons we chose to start experimenting with DOTS, and if sampling Playables or using Animation Jobs breaks determinism, they're no longer viable solutions for us.
     
    Last edited: Aug 19, 2020
  2. desertGhost_

    desertGhost_

    Joined:
    Apr 12, 2018
    Posts:
    260
    1. Create an entity for each animation driven transform.

    2. Use EntityManager.AddComponentObject() to attach the transform to the entity.

    3. Use a job like this to sync transform to translation rotation:

    Code (CSharp):
    1.  
    2.         [BurstCompile]
    3.         struct CopyFromTransforms : IJobParallelForTransform
    4.         {
    5.             [NativeDisableParallelForRestriction]
    6.             public ComponentDataFromEntity<Translation> translationLookup;
    7.          
    8.             [NativeDisableParallelForRestriction]
    9.             public ComponentDataFromEntity<Rotation> rotationLookup;
    10.  
    11.             [ReadOnly]
    12.             public NativeArray<Entity> entities;
    13.  
    14.             public void Execute(int index, TransformAccess transform)
    15.             {
    16.                 var entity = entities[index];
    17.  
    18.                 translationLookup[entity] = new Translation
    19.                 {
    20.                     Value = transform.position
    21.                 };
    22.  
    23.                 rotationLookup[entity] = new Rotation
    24.                 {
    25.                     Value = transform.rotation
    26.                 };
    27.             }
    28.         }
    Note: this job assumes entities that follow transforms are in world space and ignores animation scaling.

    I don't know if any data from mecanim or playables can be considered deterministic.
     
  3. Kelevra

    Kelevra

    Joined:
    Dec 27, 2012
    Posts:
    87
    Why not just use CopyTransformFromGameObject ? This is a standard component from Unity.Transforms.Hybrid
     
  4. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    166
    Thanks for the suggestions!

    Re CopyTransformFromGameObject: It's not documented too well. I have some questions:
    • Does it only apply to a given GameObject - Entity pair? or does it affect the entire hierarchy underneath it?
    • Does this require a call AddComponentObject on the entity with the Transform?
    • Does it copy the full world TRS or just the local TRS?
    • Can I have a root entity use CopyTransformToGameObject on the root and CopyTransformFromGameObject on it's children?
    • Is it reasonable to subclass the controlling systems to move them to another location in the system execution order?