Search Unity

Animation C# jobs in 2018.2a5

Discussion in 'Animation' started by Mecanim-Dev, Apr 4, 2018.

  1. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,283
    This was happening in a single test scene with no interfering scripts. The model in question had a single AnimationMixerPlayable playing some animations, and that playable was the input to the AnimationScriptPlayable that was playing the animation.

    In other words, root motion was off, but I wasn't moving the root transform. I'll try to create a minimal repro.
     
  2. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    the question is: does your root transform was spawn at identity or at another position/rotation?
     
  3. lifeFo

    lifeFo

    Joined:
    Apr 14, 2017
    Posts:
    15
    I use for loop to sample child transform result sample part of sub gameobject,other transform not change.
    IF i use SampleAnimation in update function,all transfrom get sample properly.
    Code (CSharp):
    1. Dictionary<string, List<Matrix4x4>> m4 = new Dictionary<string, List<Matrix4x4>> (14);
    2.         for (int i = 1; i < boneMatrices.GetLength (0) - 1; i++) {
    3.             float t = (float) (i - 1) / (boneMatrices.GetLength (0) - 3);
    4.             clip.SampleAnimation (renderer.gameObject, t);
    5.             for (int j = 0; j < bones.Length; j++) {
    6.                 var tr = bones[j];
    7.                 List<Matrix4x4> samebone;
    8.                 var cmt = rootbone.worldToLocalMatrix * tr.localToWorldMatrix * bindPoses[j];
    9.                 if (m4.TryGetValue (tr.name, out samebone)) {
    10.                     if (samebone.Contains (cmt)) {
    11.                         samebone.Add (cmt);
    12.                     } else {
    13.                         samebone.Add (cmt);
    14.                     }
    15.                 } else {
    16.                     m4[tr.name] = new List<Matrix4x4> () { cmt };
    17.                 }
    18.                 boneMatrices[i, j] = cmt;
    19.             }
    20.         }
    sample in for loop

    Code (CSharp):
    1. delt1 += Time.deltaTime;
    2.         var clip = AC[0];
    3.         var mtx = sampledBoneMatrices[0];
    4.         int framid = (int) (clip.frameRate * ((delt1 > 1 ? delt1 = 0 : delt1)));
    5.         float t = (float) (framid - 1) / (mtx.GetLength (0) - 3);
    6.         clip.SampleAnimation (target, t);
    7.  
    8.         NativeArray<Matrix4x4> boneTransforms1 = new NativeArray<Matrix4x4> (mtx.GetLength (1), Allocator.Temp);
    9.         for (int i = 0; i < boneTransforms1.Length; i++) {
    10.             var finalmatrix = rootBone.worldToLocalMatrix * bonestran[i].localToWorldMatrix * BindPoses[i];
    11.             if (!bonesmtx.Contains (finalmatrix)) {
    12.                 Debug.LogError ($"not find {bonestran[i].name}  bones corresponding mtx[framid,i]\n{mtx[framid,i]} fram={framid}");
    13.                 //  boneTransforms1[i] = finalmatrix;
    14.  
    15.             }
    16.             boneTransforms1[i] = mtx[framid, i];
    17.  
    18.         }
    sampled in update function.
    What's wrong with above code?

    right is sampled animation
     
    Last edited: Sep 4, 2019
  4. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    331
    @Mecanim-Dev
    Hi. It seems that Unity 2019.3 prevents writing values to TransformSceneHandle. (All of SetXXX methods are marked as deprecated). So is this true that after Unity 2019.3, Animation Job can't change the value of non-animated transform?

    Another question, what TransformSceneHandle's value is, if it is child of animated transform? after animated pose in current frame or previous frame's?

    This behaviors are important to implementing secondary-animation system by using Animation Job.

    In my case, my character has two bone groups, one for body, other for secondary animations (cloth, hair, and body colliders and so on). Some of secondary animation bones are children of animated bone, and others are not children.

    Currently, my secondary animation bones are modified at custom Monobehaviour.LateUpdate() and makes quite big performance degradation. So I investigating whether Animation Job will be solution.

    Thanks.
     
    Last edited: Sep 10, 2019
    awesomedata likes this.
  5. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    TransformSceneHandle was first used to write to transform not under the animator component game object hierarchy.

    We don't allow this anymore because the behaviour is not deterministic. Depending on your configuration and how many animator you have in your scene you can end up in situation where you don't get the same result depending on the instantiation order which is pretty bad and hard to debug especially with pooling.

    You can still use TransformSceneHandle to read data outside of the animator control, but you are not allowed to write to it anymore.

    If the transform is under the animator hierarchy you should use a TransformStreamHandle which should yield the correct result regardless of the instantiation order.
     
    WendelinReich and awesomedata like this.
  6. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    331
    Thanks for detailed reply. How about my second question? When I try to read the value of non-animated transform (but children of animated bone) by using TransformSceneHandle, is it previous frame's value? or current animated value?

    Also, how about that allowing writing value to TransformSceneHandle, as user's responsibility like ECS's NativeDisableParallelForRestriction attribute. If the user exactly know what they do, writing value to scene object might not be any problem. I think that Animation system does not need to be strictly deterministic sometimes (maybe almost?) and disallowing writing value to TransformSceneHandle makes Animation Job be less useful.
     
    Last edited: Sep 12, 2019
  7. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    830
    This is an interesting question. I'd like to know this as well.


    So are you saying you have two skeletons for a single character, or are some bones just not attached to the root bone?

    I've been seriously considering this setup because I want to group certain bones for different purposes too, like secondary animation, facial blendshapes, cloth attachments, weapon attachments, etc., then combine them later with their own separate animations/physics.
    Performance-wise, I can see how this can be a problem without being able to piggy-back off of other transforms.
    I was hoping DOTS-based Modular Animation Rigging would solve this issue... I just don't know how well it will work with what I have in mind. Things like Blendshapes and Cloth or piggy-backing off the transform of separate joints like it seems you are trying to do sounds like essentially the thing I'm trying to do, but in-editor and modular...


    Any idea on the efficiency (and feasibility) of the modular rigging workflow I've proposed (either now or in the near future), @Mecanim-Dev ?
     
  8. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    331
    In my case, I have base skeleton + some additional bones, which is dynamically combined in runtime (from character customization, weapon and so on). ex) BaseBoneRoot>BaseBoneHead>DynamicBoneHair
    Animator components only animates base skeleton and additional bones are only attached to it.

    Secondary animation is generated in Monobehaviour.LateUpdate() and some of ECS system. But Monobehaviour part is single threaded and slow, ECS part is quite fast but lack of character (animator) wise control for LOD system. So I'm investigating whether Animation Job can be solution (animator-wise controllable and jobified+burst performance).
     
  9. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    It always the transform value at the beginning of the animation update loop. Most of the time it the previous frame value, but if you have a system that change a transform value before the animation update loop it should be picked up by the TransformSceneHandle.
     
  10. condotelvietnam

    condotelvietnam

    Joined:
    Sep 17, 2019
    Posts:
    1
    The tears flow endlessly

    In other news. Is it better to create duplicate mirrored clips or have it done at runtime ala mecanim?
     
  11. markgrossnickle

    markgrossnickle

    Joined:
    Aug 21, 2017
    Posts:
    32
    What is the current state of animations? We are starting to move a project over to ECS. Project should be out early 2020.

    We are currently using SkinnedMesh renderers and an animator for a 3D character. Should we continue doing that and have entities link to a gameObject/monobehaviors in a hybrid approach or is the github repro in a state we should try that first and go full ecs?
     
  12. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    830
    I really want to know this too...

    Something tells me it's still very early despite being on hold for so long... I'm desperate for an animation update. D:
     
    markgrossnickle likes this.
  13. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    Hi guys,

    yes it still early, we just completed the Unite demo Dots Shooter with the new com.unity.animation package for DOTS.

    The package is suppose to ship as preview for 2019.3 with Dots Shooter but there is still a lot to do to get to the production level quality.
     
  14. Onigiri

    Onigiri

    Joined:
    Aug 10, 2014
    Posts:
    85
    is this will be similar to mecanim node editor or code only?
     
  15. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    Right now it code only, the goal for dots shooter was to reimplement the tech we had for FPS sample but in dots.
    So it graph base like Playable but completly open because you have access to the source code.

    The package currently only support Character animation, we do write the animation result to the character skin mesh matrices diretctly

    Right now we do support the following graph node:
    Mixer
    LayerMixer with override layer, additive layer, and masking.
    Generic Retargeting <---- Yes that right generic
    1d BlendTree
    2d Simple Directionnal BlendTree
    Two bone IK

    Also we do have:
    Animation curve evaluator: You can create a curve at runtime to drive any single property.
    Bone Rendering for debug.
    AnimationStream like API <---if you did create some custom AnimationJobs it pretty easy to port them to this new tech.
    Support for TRS animation curve and custom float curve.

    We are currently working on
    Root motion
    Animation Runtime Rigging
     
    ekakiya, awesomedata, Jes28 and 2 others like this.
  16. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    331
    @Mecanim-Dev Hi, I have some questions for clarification of Animation C# Jobs and Animation Rigging.

    1. What exactly transforms which TransformStreamHandle can handle? Children of Animator's transform? How about runtime-generated transform?

    2. What is different between TransformXXXHandle and ReadWrite/ReadOnlyTransformHandle in rigging package?. It seems that both handles can be used in AnimationJob.

    3. How to turn-off custom Animation Job for Animator? especially, for Animation LOD. I want to disable to my custom Animation Job of distant character for saving computation power, but I can't find any API for disable Animation Job temporarily. Should I set new job data which has immediately return method?

    Thanks.
     
  17. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    Right, Children of Animator transform.
    If you create some transform at runtime and you try to Bind them with a TransformStreamHandle, the animator will generate the missing binding, so it should works.
    But keep in mind that there is a cost to do that. Everytime that your animator will have to rebind the animation it will take a few more cpu cycle to do the same job.
    So keep an eyes on profiler marker "Animator.SetupAvatarDataSet" and make sure that it doesn't take too much time.

    Right, it handle both a TransformStreamHandle and a TransformSceneHandle, now the question is why?
    When you work with IK rig you often bake the resulting animation to either the FK or the IK.
    So in this case an IK effector can either be animated so driven by a TransformStreamHandle or manipulated by the user to set a new IK goal in which case it need to be a TransformSceneHandle.


    Unfortunately there is no built-in support for LOD in the PlayableGraph. One thing you can do is change the topology of the graph based on your LOD
     
    Kichang-Kim likes this.
  18. ahmidou_mpc

    ahmidou_mpc

    Joined:
    Aug 13, 2019
    Posts:
    9
    It seems the AnimationJob system only single threaded in 2019.2.6, is it?
     
  19. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    830
    Thanks for the updates!

    So how might one do that topology change easily? -- Any suggested method for handling this?
    Also, is this planned to be handled automatically in the future?
     
  20. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    it shouldn't, maybe there is a new regression.

    Can you log a bug?
     
  21. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    There is no many way to handle that, the playable API allow you to connect and disconnect playable, son one thing you can do is tag your playable with a LOD level and when you need to change the LOD level you also need to traverse the graph and disconnect playable that doesn't meet the LOD level requirement.

    For playable no, we don't have any LOD support for animation. So I don't think we will ever support LOD for Animation and Animator component.

    But for DOTS animation we are currently looking at different way to handle LOD.
    Either by reducing the complexity of the animation rig for different LOD, think less bone for low level LOD.
    And also by reducing the complexity of the graph, you don't need foot ik correction on character that are too far from the camera, or you may not need all the procedural node to animate props.
     
    awesomedata likes this.
  22. ahmidou_mpc

    ahmidou_mpc

    Joined:
    Aug 13, 2019
    Posts:
    9
    I'm seeing the same behavior in 2019.3b4.
    I'll try to make a simple repro and log a bug this weekend
     
  23. Unityraptor81

    Unityraptor81

    Joined:
    Nov 28, 2016
    Posts:
    18
    Hey All,

    Is there a way to "read" an animation clip bone transform properties without having an animator controller ?

    I'm working on active "physical" ragdolls and right now the only solution is to duplicate skeleton hierachy with a first invisible animated skeleton and a second active one where we physically target the transform of the first.

    This is really perf hungry. Having a simple solution to just read a clip transforms to match them would be nice, and doing this in a job would be even better.

    Thanks,

    Jay
     
  24. zarex7

    zarex7

    Joined:
    Jan 25, 2016
    Posts:
    4
    Hello all!

    Are it possible to use in Humanoid something like

    Anim.SetMuscle("Jaw")=10; ?

    to just set value to muscles by C# script?
     
  25. zarex7

    zarex7

    Joined:
    Jan 25, 2016
    Posts:
    4
    So, I found some solution... but need help to debug. So this code should open-close model's mouth every second:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class HeadRotatorMuscle : MonoBehaviour
    6. {
    7.  
    8.     //   Human muscle stuff
    9.     HumanPoseHandler humanPoseHandler;
    10.     HumanPose humanPose;
    11.     Animator anim;
    12.  
    13.     // Indexes to muscles
    14.     // 9: Neck Nod Down-Up min: -40 max: 40
    15.     // 10: Neck Tilt Left-Right min: -40 max: 40
    16.     // 11: Neck Turn Left-Right min: -40 max: 40
    17.     // 12: Head Nod Down-Up min: -40 max: 40
    18.     // 13: Head Tilt Left-Right min: -40 max: 40
    19.     // 14: Head Turn Left-Right min: -40 max: 40
    20.  
    21.  
    22.     //   Bone stuff
    23.     Transform head;
    24.     Transform jaw;
    25.     Transform leye;
    26.     Transform reye;
    27.  
    28.     // Muscle name and index lookup (See in Debug Log)
    29.     void LookUpMuscleIndex()
    30.     {
    31.         string[] muscleName = HumanTrait.MuscleName;
    32.         int i = 0;
    33.         while (i < HumanTrait.MuscleCount)
    34.         {
    35.             Debug.Log(i + ": " + muscleName[i] +
    36.                 " min: " + HumanTrait.GetMuscleDefaultMin(i) + " max: " + HumanTrait.GetMuscleDefaultMax(i));
    37.             i++;
    38.         }
    39.     }
    40.  
    41.     // Set character in fetus position
    42.     void ResetMuscles()
    43.     {
    44.         // reset all muscles to 0
    45.         for (int i = 0; i < humanPose.muscles.Length; i++)
    46.         {
    47.             //Debug.Log (humanPose.muscles [i]);
    48.         humanPose.muscles[i] = 0;
    49.         }
    50.     }
    51.  
    52.  
    53.     //   !!! Human Pose approach !!!
    54.     void Start()
    55.     {
    56.         // https://forum.unity.com/threads/humanposehandler.430354/
    57.  
    58.         // get attached Animator controller
    59.         anim = GetComponent<Animator>();
    60.  
    61.         // run this if you want the indexes to muscles on your character
    62.         LookUpMuscleIndex();
    63.  
    64.         // TODO keeping body above plane
    65.         //Vector3 current_position = transform.position;
    66.  
    67.         // get human pose handler
    68.         humanPoseHandler = new HumanPoseHandler(anim.avatar, transform);
    69.         // get human pose
    70.         humanPose = new HumanPose();
    71.  
    72.         // TODO keeping body above plane
    73.         //humanPose.bodyPosition = current_position;
    74.  
    75.         // reference pose to pose handler
    76.         humanPoseHandler.GetHumanPose(ref humanPose);
    77.  
    78.         // set a specific musle; 9: Neck Nod Down-Up
    79.         //humanPose.muscles[9] = -20f;
    80.         //Debug.Log(humanPose.muscles[9]);
    81.  
    82.         humanPose.muscles[19] = -10f;  // -10 ... 10
    83.         Debug.Log(humanPose.muscles[19]);
    84.  
    85.         // use pose information to actually set the pose; doesn't work so far
    86.         humanPoseHandler.SetHumanPose(ref humanPose);
    87.  
    88.         StartCoroutine(ExampleEvery3sec());
    89.     }
    90.  
    91.     // Update is called once per frame
    92.     void Update()
    93.     {
    94.         //humanPoseHandler.SetHumanPose(ref humanPose);
    95.     }
    96.  
    97.     IEnumerator ExampleEvery3sec()
    98.     {
    99.         //print(Time.time);
    100.         yield return new WaitForSeconds(1);
    101.         //print(Time.time);
    102.  
    103.         humanPose.muscles[19] = Random.Range(-10.0f, 10.0f);  // -10 ... 10
    104.         Debug.Log(humanPose.muscles[19]);
    105.         humanPoseHandler.SetHumanPose(ref humanPose);
    106.  
    107.     }
    108.  
    109. }
     
  26. ahmidou_mpc

    ahmidou_mpc

    Joined:
    Aug 13, 2019
    Posts:
    9
    before logging a but I just want to be sure that there's one, here's a profiler screenshot of the Animation Rigging workshop' ninja rig.
    Should it be parallelized or is it the expected behavior?
    upload_2019-10-2_19-47-16.png
     
  27. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    it should be parallelized, also I don't understand why you have a deep level callstack like this, look like you are invoking a bunch of evaluation directly from your animation jobs.

    are you using
    AnimationStream.GetInputStream()
    to invoke manually the evaluation of all the playable graph?
     
  28. ahmidou_mpc

    ahmidou_mpc

    Joined:
    Aug 13, 2019
    Posts:
    9
    All you see in that screen-shot is Animation-Rigging package related, I just opened the "SampleSceneNinja.unity" scene from that project:
    https://github.com/Unity-Technologies/animation-rigging-workshop-siggraph2019
    afaik
    AnimationStream.GetInputStream()
    is not used at all.
     
  29. ahmidou

    ahmidou

    Joined:
    Sep 17, 2012
    Posts:
    81
    @Mecanim-Dev I finally got some time to look at it again.
    It seems Animation jobs are parallelized per graph, not per job.
    If I take the Animation-Rigging 2boneIK test scene where there's 2 legs, it's running on a single thread,
    but if I duplicate the rig hierarchy, it is then distributed.
    Is it the intended behavior? If so this should be documented as it is unclear.
     
    Last edited: Oct 10, 2019
  30. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    you're right and it has been like that since we implemented mutlithreading in the animation system in 2011.

    that a look at this documentation page, you will see which animation steps are multithreaded

    https://docs.unity3d.com/Manual/ExecutionOrder.html

    Basically it StateMachineUpdate, ProcessGraph, ProcessAnimation and Write Transforms.

    We do schedule jobs per animator, not per playable in the graph, the context switch cost is too high if you start to schedule at this level of granularity.

    Also it up to the scheduler to choose how to distribute the jobs. There is a few sync point in the animation system and if the main thread is wainting on a sync point and there still jobs to execute, the main thread will start to execute jobs.

    As you add more rigged character you should see the jobs starting to distribute more evenly
     
  31. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    830
    That's a terrible place for documentation about the underlying Animation system... I really think it deserves its own section, or at least to be mentioned in the overview on animation as a footnote someplace.
     
  32. ahmidou

    ahmidou

    Joined:
    Sep 17, 2012
    Posts:
    81
    That's good to know, thanks for the explanation
    The documentation page you pointed isn't really saying that much thought. The only mention is:
     
  33. Unityraptor81

    Unityraptor81

    Joined:
    Nov 28, 2016
    Posts:
    18
    @Mecanim-Dev Any tips about this one ?
     
  34. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    You didn't see the legend?
    legend.png
     
  35. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    yes it can be done but the setup is awful, you need a animation jobs that can read all the transforms from the scene value and store the animation pose into this job so basically a job with an array of TransformSceneHandle and an array of positions and rotations

    1 . you need to deactivate the animator component when you are going to ragdoll to let the physics run the simulation.
    2. when you are ready to blend from ragdoll to animation, you need to enable back the animator and also the animation job that read all the transforms position + rotation on this frame.
    3. for a few frame you blend the result of this physics pose with your animation.
     
  36. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    1,938
    But as soon as you enabled the Animator, would it not just break the ragdoll simulation immediately?

    Even with Physics.autoSyncTransforms disabled, synchronization still happens prior to the physics simulation step.
    All we need here is bool Rigidbody.syncTransform that would be defaulted to enabled, but could be disabled by script for all the character rigidbodies to completely decouple the Transform and Rigidbody components.

    That way we could leave our Animator enabled at all times, have ragdolls manipulated via joints and AddForce only and have an animation job take care of the blending between ragdoll and animated pose (Would probably need something like RigidbodySceneHandle to read Rigidbody.position and rotation). That would enable us also to do partial blending, like having the arms dangle around with the rest of the body animated and all kinds of other cool stuff.

    Best,
    Pärtel
     
  37. Mecanim-Dev

    Mecanim-Dev

    Unity Technologies

    Joined:
    Nov 26, 2012
    Posts:
    1,660
    yes you're right, hence why I said that the setup is awful, it the only way I managed to make it work without changing the physics code.

    You can already read the value of Rigidbody.position and rotation with a PropertySceneHandle of type float. You need three handle for .x, .y, .z

    As for a better integration with physics, I've been pushing on this since 2016 but there is always something more important on the road map and I do not control the road map so ....
     
    Partel-Lang likes this.
  38. Unityraptor81

    Unityraptor81

    Joined:
    Nov 28, 2016
    Posts:
    18