Search Unity

Having an issue with IK (catching projectile)

Discussion in 'Animation' started by AxisUnity, Nov 23, 2017.

  1. AxisUnity

    AxisUnity

    Joined:
    May 16, 2017
    Posts:
    12
    Hello,

    The avatar I am working with right now is a baseball catcher. I use IK to have the mitt be in the correct position for the catch. The closer the ball is from the mitt, the higher I set the IK weight value. The avatar correctly stretch it's arms when the ball is in movement. I have two colliders, one on the ball and the other on the mitt. When they collide, I set the ball's parent transform to be the mitt and reset it's local position so that it's in the correct position. I then stop it's trajectory and let the rest of the catching animation continue.

    Now here is the issue, the animator seems to forget about the last SetIKPosition() and/or weight, and continue the animation as if it was never set. After the ball's parent changed, in the Update() of my IkController script I can see that the ball is still in the correct position, right after this however, OnAnimatorIK() is called and the ball is suddenly in the wrong position (along with the rest of the avatar, which is just continuing it's animation as if there were never any IK set). So visually it's arm is suddenly in a very different position after just one frame.

    One thing I noticed that might have something with the problem, is that in OnAnimatorIK(), if I do GetIKPositionWeight() before setting it, it always return 0 and similarly with GetIKPosition(), it does return me a position, but not the one I set the previous time.

    If someone has an idea of what could be going on or something I could try to fix this, i'm all ears.

    Running on unity 2017.1.2p2

    Edit: Another thing I've noticed is that it really does seems to be related to the parenting of the ball to the glove. If I change it so that the ball's parent does not become the mitt, but instead only set it's position to the mitt's position in the LateUpdate() (after IK value changed) and keep setting the IK position to the ball while gradually reducing the IK weigth overtime, the animation will gradually return to it's original "no IK" state. Since SetIKPosition() takes a Vector3 and not a Transform, I'm still very confused as to why changing the hierarchy affects the IK in such a way.
     
    Last edited: Nov 23, 2017
  2. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    theANMATOR2b likes this.
  3. AxisUnity

    AxisUnity

    Joined:
    May 16, 2017
    Posts:
    12
    I'm guessing this is a bit hard to explain without seeing the issue first hand and without seeing the actual sequencing in the code. I have been using world space positions for the IK. In my edit I mentionned that the IK is working just fine if I don't change the ball's hierarchy (yes I still have to do a blend out of the IK after the catch). But if I change the ball's parent, even before I have time to do a blend out, the ball's position has already been modified wrongfully by the IK (the anim is playing normally as if there was no IK anymore). If I look at the values set in the update right before the catch, the SetIKPosition is in the correct position, the SetWeight is also correct, the position of the ball after the SetParent is correct too. Even in the Update() of the IKController the ball's position is correct, but for the OnAnimatorIK() right after, ball is in wrong position, before I even had time to do the blending out.

    I'm not sure if this will be usefull information or if it's a better way to visualise the sequencing, but here is a what's happening with the ball's position (at different times in the code between two OnAnimatorIK()) with semi-pseudocode:

    - The frame right before catch in IKController.OnAnimatorIK():
    animator.SetIKPosition(Avatar.LeftHand, (0.1, 1.0, 1.0)); //(this is where the ball currently is, so Ik is set to this position)
    targetPosition == (0.0, 1.1, 1.0); //(this is where the ball is going towards)
    animator.SetIKWeight(Avatar.LeftHand, 0.96f); //(the ball is very close to the target position, so the weight is high)

    - Collision with glove detected
    ball.transform.SetParent(glove.transform, true); (I set the ball's parent without changing it's world position)
    ball.transform.localPosition = Vector3.zero; (reset it's local position relative to the glove)
    ball.transform.position == (0.1, 1.0, 0.9) (the ball is now in the correct position after the parent change)

    In IKController.Update(), Ball.Transform.Position == (0.1, 1.0, 0.9) (the ball is still in the correct position)
    In the OnAnimatorIK(), Ball.Transform.Position == (-0.2, 1.0, 0.5) (the ball's position relative to the glove is still fine, but it is the wrong position, because the animation is playing as if the previous SetIKPosition or weight never occured). If I call animator.GetIKPositionWeight() before setting it, it always returns 0.
     
  4. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    I don't see anything wrong so please log a bug with a small repro project to allow us to investigate the issue.