Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Humanoid IK in Playables

Discussion in 'Animation' started by Baste, Oct 24, 2017.

  1. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    Is there currently any kind of IK-solving playable available?

    I'm playing animations by setting up the playable graph and the clips and mixers and all that from script, and playing them there.

    The only way I can figure out to do IK is to add an empty animatorController into the mix, and give it an IK pass. That seems a bit strange? It works, but looking at this blog post, there seems to at least be plans for some kind of custom IK, but only in the context of the job system. I'd love to be able to be able to have the IK live in a playable I can handle in a generic way, instead of having it be a special case thing that's distinct from the rest of the graph.
     
  2. TantzyGames

    TantzyGames

    Joined:
    Jul 27, 2016
    Posts:
    51
    You can activate foot ik with AnimationClipPlayable.SetApplyFootIK(bool value), which replicates the option in mecanim.

    Otherwise, I'm using FinalIK so I haven't really delved into humanoid IK, but I'm pretty sure the IK example from the post is what we can look forward to sometime (hopefully) next year when we have real multi-threaded playables with the C# jobs system.
     
  3. TantzyGames

    TantzyGames

    Joined:
    Jul 27, 2016
    Posts:
    51
    It seems odd that it's not possible to activate an IK pass from AnimationLayerMixerlayable. We can only give it a mask or set it to additive. The IK must be separate to the playables system.

    Would it be easier to do your IK in lateUpdate than adding an empty animationController?
     
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    You mean as in manually moving the transforms? I'd really rather not do that! I did some testing, and Mechanim's IK is fast, and it's very convenient to use.
     
  5. mangax

    mangax

    Joined:
    Jul 17, 2013
    Posts:
    334
    Hello, have anyone figured away to control IK in playables?

    i tried googling around to find any topic regarding controlling IK through playables, but i couldn't find a solution or any working example around.. the blog post from unity : https://blogs.unity3d.com/2017/08/02/unity-2017-1-feature-spotlight-playable-api/
    seems to contains some classes that don't exist in the latest unity 2018 beta

    i was wondering what's the current official approach of using IK with the new playables?
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    Still doing what I wrote in the first post, using an AnimatorController with no states and an IK pass.

    You need an animator anyway for IK, so it's not that much of a hassle, but I'd like to be able to ditch that hack.
     
  7. mangax

    mangax

    Joined:
    Jul 17, 2013
    Posts:
    334
    hey baste! thanks for replay!

    i tried your way, and it's working.. but using animator controller with ik pass , then using OnAnimatorIK calls felt like am hardwiring things..
     
  8. KYL3R

    KYL3R

    Joined:
    Nov 16, 2012
    Posts:
    134
    The Examples are now online: https://github.com/Unity-Technologies/animation-jobs-samples

    Including Full-Body-IK.

    But I have no Idea when / how the IK is done.
    In Addition to "SetApplyFootIK" (what TantzyGames mentioned) you also have "SetApplyPlayableIK()" which should enable the IK Pass (OnAnimatorIK).

    The Full-Body-IK-Job actually calls "humanStream.solveIK()" but I cannot get any non-solved IK positions. I'd like to read the normal animated positions of the Hand for example. Apparently the job just goes from one IK position to the next, skipping the animation step - it's probably combining the results directly. Which is bad, because I need that information to raycast from there...

    Does anybody know how to do that?
     
  9. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    Hi,

    yes of course you can, you simply need to call
    https://docs.unity3d.com/ScriptRefe...ons.AnimationHumanStream.GetGoalPosition.html
    https://docs.unity3d.com/ScriptRefe...ons.AnimationHumanStream.SetGoalRotation.html

    it will return the blended IK position computed by all the previous playable, it up to you to activate the weight manually and either do a direct IK pass in your animation jobs with
    https://docs.unity3d.com/ScriptReference/Experimental.Animations.AnimationHumanStream.SolveIK.html

    or like you found you can also just activate SetApplyFootIK() on your playable to get an automatic IK pass at the end of the animation step
     
  10. KYL3R

    KYL3R

    Joined:
    Nov 16, 2012
    Posts:
    134
    @Mecanim-Dev Well I thought so, but it does not work for me:

    I run this code in Update(), LateUpdate(), OnAnimatorIK() etc...

    Code (CSharp):
    1.     var job = m_IKPlayable.GetJobData<FullBodyIKJob>();
    2.     var stream = new AnimationStream();
    3.     if (m_Animator.OpenAnimationStream(ref stream))
    4.     {
    5.         AnimationHumanStream humanStream = stream.AsHuman();
    6.         Vector3 pos = humanStream.GetGoalPosition(AvatarIKGoal.LeftFoot);
    7.         Debug.DrawLine(pos, pos + Vector3.right, Color.red, 1f);
    8.     }
    But it's never drawing a line where the Foot would be without IK.

    See the video:


    The Handles have a weight of 0 on the left, but weight of 1 on the right. Therefore the Foot is not moving, but you can guess the animation from the other side and also the joint moving.
    I would expect the red line to be moving just like the Foot on the left (with a time offset of course).

    I tried a lot more already, that you can read here: https://forum.unity.com/threads/c-a...how-to-obtain-non-solved-ik-positions.730673/

    I'm very thankful for help :)
     
  11. KYL3R

    KYL3R

    Joined:
    Nov 16, 2012
    Posts:
    134
  12. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    @KYL3R Mystery resolved. We had a memory stomp when using Animator.OpenAnimationStream(ref stream), it stomp the goal position.
     
    LudiKha likes this.
  13. LudiKha

    LudiKha

    Joined:
    Feb 15, 2014
    Posts:
    140
  14. LudiKha

    LudiKha

    Joined:
    Feb 15, 2014
    Posts:
    140
    I found a solution/workaround for those who stumble upon this thread with the same issue.

    The only way I've found to currently get the bone position in an animation job before IK is applied, is by using humanStream.GetGoalPositionFromPose(goal);.

    Example that works:
    Code (CSharp):
    1. // Gets the animated positions _before_ IK is applied
    2. var leftFootAnimatedPosition = humanStream.GetGoalPositionFromPose(AvatarIKGoal.LeftFoot);
    3. var rightFootAnimatedPosition = humanStream.GetGoalPositionFromPose(AvatarIKGoal.RightFoot);
    4. // Do stuff with animated position
    5. // Solve IK
    6. humanStream.SolveIK();
    7. // This works
    8.  
    For good measure here's an example that doesn't work when a previous frame had IK applied
    Code (CSharp):
    1. // This returns the previous frame IK position
    2. var leftFootAnimatedPosition = stream.GetPosition(leftFootHandle);
    3. // Solve IK
    4. humanStream.SolveIK();
    5. // This does _not_ work as intended
    6.  
     
    FlavioIT likes this.