Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

As-Pure-As-Possible ECS Animation?

Discussion in 'Data Oriented Technology Stack' started by florianhanke, Jun 23, 2019.

  1. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    60
    Hi all

    I've been experimenting with using pure ECS (including hybrid rendering, physics), which works great so far.

    Now, I've tried to see how close I could get to pure ECS animations. I'm assuming that Unity is not there yet, apart from baking animations into textures etc.

    To animate, I'm using the excellent c# animation jobs, that I start from a system:

    Code (CSharp):
    1. using Unity.Collections;
    2. using Unity.Mathematics;
    3. using UnityEngine;
    4.  
    5. namespace BUD.Animations
    6. {
    7.     public struct HumanoidMixerJob : IAnimationJob
    8.     {
    9.         public NativeArray<TransformStreamHandle> handles;
    10.         public NativeArray<float> boneWeights;
    11.  
    12.         // Weights. These are updated and passed to this job.
    13.         public float stance;
    14.         public float velocity;
    15.         public float rotation;
    16.  
    17.         public void ProcessRootMotion(AnimationStream stream)
    18.         {
    19.           // ...
    20.         }
    21.  
    22.         public void ProcessAnimation(AnimationStream stream)
    23.         {
    24.           // ...
    25.         }
    26.     }
    27. }
    However, since I need bones from an avatar, I currently need an Animator, which to my knowledge I can't attach to an entity. And so I have to give up running it on pure, and instead move to hybrid:

    Code (CSharp):
    1.  
    2.                 var entity = entityManager.CreateEntity(infantryArchetype);
    3.                 var go = Object.Instantiate(infantryPrefab);
    4.                 // Connect the entity and the GO.
    5.                 GameObjectEntity.AddToEntity(EntityManager, go, entity);
    6.  
    7.                 // Setting other components here.            
    8.  
    9.                 // Animation
    10.                 entityManager.SetComponentData<HumanAnimation>(entity, new HumanAnimation()
    11.                 {
    12.                     stance = 0.0f,
    13.                     velocity = 1.0f,
    14.                     rotation = 0.0f,
    15.                 });
    16.                 var animator = go.GetComponent<Animator>();
    17.                 // HumanoidAnimation handles setting up the job correctly.
    18.                 var humanoidAnimation = new HumanoidAnimation(animator);
    19.                 // AnimationSystem is just a dictionary where I remember which entity
    20.                 // owns the animation+animator.
    21.                 // I am aware that using entity.Index is not a good idea, but it's good enough
    22.                 // for experimenting.
    23.                 AnimationSystem.animations.Add(entity.Index, humanoidAnimation);
    24.  
    But, if I do this, of course I'll get two visible objects. An animated GO and a non-animated entity that is rendered via hybrid.

    Pure ECS and GO.gif

    I'd like to get as close to pure ECS as possible so that I can switch to whatever pure ECS animator+avatar is released at some point in the future, but so that I can continue working with what I have at the moment. From forum entries I see that they were initially planned for sometime now and that they are working on it.

    The options I see:
    1. Move to hybrid, and do not use the hybrid renderer so that I only work with the GO.
    2. Somehow animate the entity by somehow connecting the animator/avatar/bones to the entity (I assume that's not possible)?
    3. Forget animations for now and work on something else.
    4. Or, one of you has an idea on how to get closer to pure ECS? (Sadly, baking the animations into textures is not yet an option as I need the animations to be quite dynamic/blended)

    Many thanks in advance!
     
    Opeth001 likes this.
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    623
    So to get rid of the animator dependency, you need to extract the bones and the animation clips into entities and blobs. Joachim's example already shows how to do most of this. Then instead of using animation jobs, you can instead use ECS jobs to drive the bones.

    To get the animations rendered, you have a couple approaches:
    1. Use a material property block pool to write your bone positions and use Graphics.DrawMesh. This gives you the highest quality skinning for a small number of meshes.
    2. Write your bone matrices to a compute buffer and use a custom vertex skinning shader. You can make instancing work with this approach but you are more limited in how many bone influences per vertex you implement. This doesn't scale as well as the texture animation approach but I think you could get a few hundred or maybe even a couple thousand skinned meshes with this approach.
     
    wobes likes this.
  3. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    60
    twobob likes this.
  4. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    623
    Yes it is, particularly the authoring code using GameObject Conversion.
     
    florianhanke likes this.
  5. twobob

    twobob

    Joined:
    Jun 28, 2014
    Posts:
    1,785
    did you get this done?
     
  6. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    60
    No, the DOTS animation package was announced shortly after, so I decided to wait for it.
     
    twobob and siggigg like this.
  7. iMancha

    iMancha

    Joined:
    Sep 22, 2014
    Posts:
    10
    @florianhanke Where did you see the announcement, I would to follow this topic closely as my project requirements are similar.
     
  8. florianhanke

    florianhanke

    Joined:
    Jun 8, 2018
    Posts:
    60
    ConAim likes this.
  9. iMancha

    iMancha

    Joined:
    Sep 22, 2014
    Posts:
    10