Search Unity

How should I store and access groups of animation curves (BlobAsset)?

Discussion in 'Entity Component System' started by Antypodish, Apr 10, 2021.

  1. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Just to be clear, I want to avoid using unity.animation at given time, so I am looking for custom simplified solution, if possible.

    Imagine animated mesh with few bones.
    Each bone is animated by a corresponding AnimationCurves in the system.
    And potentially blended between two animations.

    I looked into BlobAssetSimple of BlobAsset
    EntityComponentSystemSamples/ECSSamples/Assets/Advanced/BlobAssetSimple/
    https://github.com/Unity-Technologi...d1/ECSSamples/Assets/Advanced/BlobAssetSimple

    And more complex example BlobAssetScalable
    EntityComponentSystemSamples/ECSSamples/Assets/Advanced/BlobAssetScalable/
    https://github.com/Unity-Technologi.../ECSSamples/Assets/Advanced/BlobAssetScalable

    So the first BlobAssetSimple example shows animated cube, using BlobAsset.
    Its animation bobs up and down. Simple position curve.

    upload_2021-4-10_12-36-20.png

    Code (CSharp):
    1. partial class SimpleBlobAnimationSystem : SystemBase
    2. {
    3.     protected override void OnUpdate()
    4.     {
    5.         var dt = Time.DeltaTime;
    6.         Entities.ForEach((ref SimpleBlobAnimation anim, ref Translation translation) =>
    7.         {
    8.             anim.T += dt;
    9.             translation.Value.y = anim.Anim.Value.Evaluate(anim.T);
    10.         }).Run();
    11.     }
    12. }
    I understand the concept of assigning animation curve inside a blob and component, which is then attached to the entity.

    Now, my challenge is, how I retrieve multiple curves for that entity (bone)?
    For example I want to play specific set of animation curves, for selected bones.
    But I may want later play different set of animations curves too for that bone.

    By what I see in the first example, the BlobAsset assigns only one curve reference to the entity component.
    And what I need, is to be able select, which curves I want to get from BlobAsset, to be played.


    In second BlobAssetScalable sample, I am not sure if it is best example. I don't get its point.
    Is more advanced, but use case is rather missing the point in my opinion. Or I miss understand the concept.
    The sample shows few hundreds of cubes rendered.

    upload_2021-4-10_12-35-44.png

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Mathematics;
    3. using Unity.Transforms;
    4. using UnityEngine;
    5.  
    6. [ExecuteAlways]
    7. public class MeshBBRenderSystem : ComponentSystem
    8. {
    9.     protected override void OnUpdate()
    10.     {
    11.         Entities.ForEach((Entity e, ref MeshBBComponent dmc, ref Translation t) =>
    12.         {
    13.             var min = dmc.BlobData.Value.MinBoundingBox;
    14.             var max = dmc.BlobData.Value.MaxBoundingBox;
    15.  
    16.             // Draw a bounding box
    17.             Debug.DrawLine(t.Value + new float3(min.x, min.y, min.z), t.Value + new float3(max.x, min.y, min.z));
    18.             Debug.DrawLine(t.Value + new float3(min.x, max.y, min.z), t.Value + new float3(max.x, max.y, min.z));
    19.             Debug.DrawLine(t.Value + new float3(min.x, min.y, min.z), t.Value + new float3(min.x, max.y, min.z));
    20.             Debug.DrawLine(t.Value + new float3(max.x, min.y, min.z), t.Value + new float3(max.x, max.y, min.z));
    21.  
    22.             Debug.DrawLine(t.Value + new float3(min.x, min.y, max.z), t.Value + new float3(max.x, min.y, max.z));
    23.             Debug.DrawLine(t.Value + new float3(min.x, max.y, max.z), t.Value + new float3(max.x, max.y, max.z));
    24.             Debug.DrawLine(t.Value + new float3(min.x, min.y, max.z), t.Value + new float3(min.x, max.y, max.z));
    25.             Debug.DrawLine(t.Value + new float3(max.x, min.y, max.z), t.Value + new float3(max.x, max.y, max.z));
    26.  
    27.             Debug.DrawLine(t.Value + new float3(min.x, min.y, min.z), t.Value + new float3(min.x, min.y, max.z));
    28.             Debug.DrawLine(t.Value + new float3(max.x, min.y, min.z), t.Value + new float3(max.x, min.y, max.z));
    29.             Debug.DrawLine(t.Value + new float3(min.x, max.y, min.z), t.Value + new float3(min.x, max.y, max.z));
    30.             Debug.DrawLine(t.Value + new float3(max.x, max.y, min.z), t.Value + new float3(max.x, max.y, max.z));
    31.         });
    32.     }
    33. }
    Basically what job does, it retrieves common bounding box min/max and assigns corresponding offset entity offset.
    Each box has same dimensions right? So that why I think example is rather bad and missing the point.
    But I digress.


    The matter is, that I don't know yet, how I could grab multiple animation curves. How to adapt either of script, to do so. As far I am aware, I can not use DynamicBuffers with blobs.


    Option 1:

    By looking on both example, my one of thought is, putting each animation curve per designated "curve" entity. So each entity will hold own curve component with its blob.
    Then have another set of animation entities, which each holds dynamic buffer, of grouped curve entities.
    Then I can call in the system entity bone, to play desired animation, by referencing animation entity (or 2 for blending) and get each animation curve, by getting curve entities (pos, rot, xyz (up to 6 curve entities)), from dynamic buffer of animation entity.

    This is doable, but seems overly referencing too many entities in chain.


    Option 2:

    Another though is, using other type of store, like multiHashMap, where I store animation IDs as keys and groups of curves as values, per each key. Now I am thinking, how should I store then curves? As entities with component holding blob reference with curve, or can I actually store animationCurve directly in multiHashMap (haven't tried yet), which I can later access in job and burst? But If I can store in, then I don't need blob asset at all, right?


    Option 3:

    Last option, based on second git example, is using BlobAssetComputationContext.

    Code (CSharp):
    1.  
    2.             // Third step, create the ECS component with the associated blob asset
    3.             var index = 0;
    4.             Entities.ForEach((MeshToBoundingBoxAuthoring auth) =>
    5.             {
    6.                 context.GetBlobAsset(processBlobAssets[index++], out var blob);
    7.                
    8.                 // Create the ECS component for the given GameObject
    9.                 var entity = GetPrimaryEntity(auth);
    10.  
    11.                 DstEntityManager.AddComponentData(entity, new MeshBBComponent(blob));
    12.                 DstEntityManager.AddComponentData(entity, new Translation {Value = auth.transform.position});
    13.             });
    14.  
    I could store animation curves as blobs, in persistent BlobAssetComputationContext store and retrieve each individual curve, by corresponding hash. Then it is just matter, how I store groups of animation curves. Perhaps I could have another BlobbAsset, or even MultiHashMap, to get curves ID, per animation.


    Option 4:

    ??


    Any advice would be highly appreciated.
     
    Last edited: Apr 10, 2021
  2. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Not sure if this what you want, but for storing AnimationCurve as blobs I've used this as a base:
    https://forum.unity.com/threads/a-fast-blobcurve.985941/

    TL;DR: Store actual values of the AnimationCurve (bootstrap them, or convert) to blob data via BlobBuilder;
    Gathering multiple curves into single "group" should be pretty trivial from there on.
     
    Antypodish likes this.
  3. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Thx, I am checking it out now.
     
  4. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    Why? You can use it. You can put BlobAssetReference inside IBufferElementData, for example, we use this in one of our DynamicBuffer's:
    BlobAssetReference<BlobArray<float3>>
     
    Antypodish likes this.
  5. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Oh that's cool. I read I think official comments, that they are not supported in buffers. But if so, that make things much easier for me.