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

Resolved Animation unintentional node sharing?

Discussion in 'DOTS Animation' started by thelebaron, Feb 25, 2021.

  1. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    857


    So for some reason my characters appear to be sharing the node data from a particular entity/node, you can see they all share the same parameter although I am unsure why. Is this a bug? Is this my own doing?


    Anyway: Entities get a new destination and move to it. Should be simple enough. Destination+Rotational code is handled by a system, which also sets a speed parameter to a component.
    Animation should read this component and react to it, which it does.. but it appears to share the node data of one of the entities, I think its always of the most recently created entity that appears to override the others.

    I'm making new nodes for each entity, from my own viewpoint no data should really be shared among entities besides the initial clip blob assets from conversion. Each entity also has its own unique component data.
    My graph setup code + a simple control node below, there's another wander system that plugs in a random destination which entities move+rotate towards(but it doesnt touch animation parameters). Theres a control node that sets the speed from component data and is connected into the blend weight but again they should be unique nodes?

    Though I feel like the graph setup should be the only real relevant code here but I've also added all the related scripts for viewing.


    Code (CSharp):
    1.  
    2. using Unity.Animation;
    3. using Unity.Collections;
    4. using Unity.DataFlowGraph;
    5. using Unity.Entities;
    6.  
    7. namespace Modules.Animation.Samples
    8. {
    9.     [UpdateBefore(typeof(DefaultAnimationSystemGroup))]
    10.     public class StupidSimple_GraphSystem : SystemBase
    11.     {
    12.         private ProcessDefaultAnimationGraph animationGraph;
    13.        
    14.         protected override void OnCreate()
    15.         {
    16.             base.OnCreate();
    17.             animationGraph = World.GetOrCreateSystem<ProcessDefaultAnimationGraph>();
    18.             animationGraph.AddRef();
    19.             animationGraph.Set.RendererModel = NodeSet.RenderExecutionModel.Islands;
    20.         }
    21.        
    22.         protected override void OnUpdate()
    23.         {
    24.             var postUpdateCommands = new EntityCommandBuffer(Allocator.Temp);
    25.             // Create graph
    26.             Entities.WithNone<StupidSimple_Inputs>().ForEach((Entity entity, ref Rig rig, ref StupidSimple_Setup setup) =>
    27.             {
    28.                 var set  = animationGraph.Set;
    29.                 var inputs = new StupidSimple_Inputs
    30.                 {
    31.                     Graph = animationGraph.CreateGraph(),
    32.                     Speed                = 1.0f
    33.                 };
    34.                
    35.                 var entityNode      = animationGraph.CreateNode(inputs.Graph, entity);
    36.                 var deltaTimeNode   = animationGraph.CreateNode<ConvertDeltaTimeToFloatNode>(inputs.Graph);
    37.                 var timeCounterNode = animationGraph.CreateNode<TimeCounterNode>(inputs.Graph);
    38.                 var controlNode     = animationGraph.CreateNode<StupidSimple_ControlNode>(inputs.Graph);
    39.                 var localToRootNode = animationGraph.CreateNode<GetAnimationStreamLocalToRootNode>(inputs.Graph);
    40.                 var physicsNode     = animationGraph.CreateNode<PhysicsVelocityNode>(inputs.Graph);
    41.                 var mixerNode = animationGraph.CreateNode<MixerNode>(inputs.Graph);
    42.                 var clip0     = animationGraph.CreateNode<ClipPlayerNode>(inputs.Graph);
    43.                 var clip1     = animationGraph.CreateNode<ClipPlayerNode>(inputs.Graph);
    44.                
    45.                 set.Connect(entityNode, controlNode, StupidSimple_ControlNode.KernelPorts.Input, NodeSetAPI.ConnectionType.Feedback);
    46.                 set.Connect(entityNode, deltaTimeNode, ConvertDeltaTimeToFloatNode.KernelPorts.Input, NodeSetAPI.ConnectionType.Feedback);
    47.                 set.Connect(entityNode, physicsNode, PhysicsVelocityNode.KernelPorts.LocalToWorld, NodeSetAPI.ConnectionType.Feedback);
    48.                 set.Connect(entityNode, physicsNode, PhysicsVelocityNode.KernelPorts.PhysicsMovementComponent, NodeSetAPI.ConnectionType.Feedback);
    49.                 set.Connect(entityNode, physicsNode, PhysicsVelocityNode.KernelPorts.InputsComponent, NodeSetAPI.ConnectionType.Feedback);
    50.                
    51.                 set.Connect(controlNode, StupidSimple_ControlNode.KernelPorts.Output, mixerNode, MixerNode.KernelPorts.Weight);
    52.                 set.Connect(deltaTimeNode, ConvertDeltaTimeToFloatNode.KernelPorts.Output, timeCounterNode, TimeCounterNode.KernelPorts.DeltaTime);
    53.                 set.SetData(timeCounterNode, TimeCounterNode.KernelPorts.Speed, 1);
    54.                
    55.                 set.Connect(clip0, ClipPlayerNode.KernelPorts.Output, mixerNode, MixerNode.KernelPorts.Input0);
    56.                 set.Connect(clip1, ClipPlayerNode.KernelPorts.Output, mixerNode, MixerNode.KernelPorts.Input1);
    57.                 set.Connect(timeCounterNode, TimeCounterNode.KernelPorts.OutputDeltaTime, clip0, ClipPlayerNode.KernelPorts.DeltaTime);
    58.                 set.Connect(timeCounterNode, TimeCounterNode.KernelPorts.OutputDeltaTime, clip1, ClipPlayerNode.KernelPorts.DeltaTime);
    59.                 set.SetData(clip0, ClipPlayerNode.KernelPorts.Speed, 1);
    60.                 set.SetData(clip1, ClipPlayerNode.KernelPorts.Speed, 1);
    61.  
    62.                
    63.                 set.Connect(mixerNode, MixerNode.KernelPorts.Output, localToRootNode, GetAnimationStreamLocalToRootNode.KernelPorts.Input);
    64.                 set.Connect(localToRootNode, GetAnimationStreamLocalToRootNode.KernelPorts.Translation, physicsNode, PhysicsVelocityNode.KernelPorts.Translation);
    65.                 set.Connect(physicsNode, PhysicsVelocityNode.KernelPorts.Ouput, entityNode, NodeSetAPI.ConnectionType.Normal);
    66.                 set.Connect(mixerNode, MixerNode.KernelPorts.Output, entityNode, NodeSetAPI.ConnectionType.Normal);
    67.                
    68.                 set.SendMessage(localToRootNode, GetAnimationStreamLocalToRootNode.SimulationPorts.Rig, rig);
    69.                 set.SendMessage(mixerNode, MixerNode.SimulationPorts.Rig, rig);
    70.                 set.SendMessage(clip0, ClipPlayerNode.SimulationPorts.Rig, rig);
    71.                 set.SendMessage(clip1, ClipPlayerNode.SimulationPorts.Rig, rig);
    72.                 set.SendMessage(clip0, ClipPlayerNode.SimulationPorts.Configuration, setup.Configuration);
    73.                 set.SendMessage(clip1, ClipPlayerNode.SimulationPorts.Configuration, setup.Configuration);
    74.                 set.SendMessage(clip0, ClipPlayerNode.SimulationPorts.Clip, setup.IdleClip);
    75.                 set.SendMessage(clip1, ClipPlayerNode.SimulationPorts.Clip, setup.WalkClip);
    76.                
    77.                
    78.                 //postUpdateCommands.AddComponent<NpcGraphInternal>(entity);
    79.                 postUpdateCommands.AddComponent(entity, inputs);
    80.             }).WithStructuralChanges().WithoutBurst().Run();
    81.  
    82.             // Destroy graph
    83.             Entities.WithNone<StupidSimple_Setup>().ForEach((Entity e, ref StupidSimple_Inputs data) =>
    84.             {
    85.                 //DestroyGraph(e, animationGraph, ref data);
    86.                 animationGraph.Dispose(data.Graph);
    87.                 postUpdateCommands.RemoveComponent<StupidSimple_Inputs>(e);
    88.             }).WithStructuralChanges().WithoutBurst().Run();
    89.            
    90.            
    91.             postUpdateCommands.Playback(EntityManager);
    92.             postUpdateCommands.Dispose();
    93.         }
    94.        
    95.         protected override void OnDestroy()
    96.         {
    97.             if (animationGraph == null)
    98.                 return;
    99.  
    100.             var commandBuffer = new EntityCommandBuffer(Allocator.Temp);
    101.             Entities.ForEach((Entity e, ref StupidSimple_Inputs data) =>
    102.             {
    103.                 animationGraph.Dispose(data.Graph);
    104.                 commandBuffer.RemoveComponent<StupidSimple_Inputs>(e);
    105.             }).WithStructuralChanges().WithoutBurst().Run();
    106.  
    107.             commandBuffer.Playback(EntityManager);
    108.             commandBuffer.Dispose();
    109.  
    110.             animationGraph.RemoveRef();
    111.             base.OnDestroy();
    112.         }
    113.     }
    114. }
    115.  
    116. public class StupidSimple_ControlNode : KernelNodeDefinition<StupidSimple_ControlNode.KernelDefs>
    117. {
    118.     public struct KernelDefs : IKernelPortDefinition
    119.     {
    120.         public DataInput<StupidSimple_ControlNode, StupidSimple_Inputs>  Input;
    121.        
    122.         public DataOutput<StupidSimple_ControlNode, float> Output;
    123.     }
    124.  
    125.     struct KernelData : IKernelData {}
    126.  
    127.     [BurstCompile]
    128.     struct Kernel : IGraphKernel<KernelData, KernelDefs>
    129.     {
    130.         public void Execute(RenderContext ctx, in KernelData data, ref KernelDefs ports)
    131.         {
    132.             var input = ctx.Resolve(ports.Input);
    133.             ctx.Resolve(ref ports.Output) = input.Speed;
    134.         }
    135.     }
    136. }
    137.  
     

    Attached Files:

  2. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    857
    for reference this is what its supposed to look like when it works (it works properly with a single animated character)




    As for debugging if I log the output the weight value of each
    MixerNode
    each has a correct weight value(ie 1 when moving or zero when not moving) but the resulting stream definitely does not reflect the actual value of that weight when there is more than one animated character.
    So seems like a serious bug unless there is something I'm overlooking?
     
  3. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    857
    Ok false alarm, I forgot this line in my custom shader
    #define _SkinMatrixIndex UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(float, Metadata__SkinMatrixIndex)


    and all is working properly :)

     
    Krajca and Lukas_Kastern like this.