Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question Problems with 2D bones, Animation and Inverse Kinematics

Discussion in 'Animation' started by Destriarch, May 6, 2024.

  1. Destriarch

    Destriarch

    Joined:
    Feb 18, 2020
    Posts:
    9
    I'm using Unity's 2D animation system to animate a character. They're a pretty standard humanoid sprite with two legs and two arms.

    In order to be able to change the images on individual parts of the model, I have separated it into several sprites - one for each limb, the body, the head, the eyes and the mouth. I then assemble it in the editor by creating and skinning each one of them as its own skinned sprite and parenting them to the correct bones. This lets me animate them as a whole, while swapping independent parts at will to achieve things like facial expressions, gripping hands and mouth animation.

    However, I have a problem. I want to have the sprite point his hand at a particular target. In order to do this, I need to somehow override the current animation for a portion of the model with my own values. I've tried a couple of methods to achieve this, with no luck.

    First I tried using LateUpdate to manually set the bone's rotation. I tried modifying rotation, localRotation and localEulerAngles, all with the same effect. It just made the sprites move to completely incorrect positions, even though I was only changing their angle. Basically, the arm detached from the body and the hand from the arm, possibly because they were different sprites parented to those bones. What's more the animation was still affecting them, as if it were being applied after LateUpdate.

    So I tried adding Inverse Kinematics. I tried putting it on the parent object and on the individual sprite to be affected. In both cases it partially worked in that the arm would point to the target, but again the individual sprites got ripped apart so that they were no longer attached in the correct places.

    Can anyone explain what I'm doing wrong? Or is this simply not possible because you can't use the sprite resolver to change a portion of a rigged sprite without changing all of that sprite?
     
  2. Destriarch

    Destriarch

    Joined:
    Feb 18, 2020
    Posts:
    9
    *sigh* I think I have some kind of weird mental problem, where whenever I ask a question about coding, I almost immediately find the answer on my own. Here we go.

    First off, there's a kind of issue with 2D animation. You have to perform the modification to the bones after the animator has done its work, but before IK and sprite skinners have updated. To do this, you can add this line before the class declaration:

    [DefaultExecutionOrder(-15)]

    ...BUT there's a wrinkle. I added this to my main player controller class initially, because that's what was controlling the arms, and it didn't seem to work. Then I had a thought: the player controller class also sends orders to the animator. maybe this was affecting its own execution order? So I separated the code for controlling the arms out into a different class which I called 'PointingManager', moved across all the code needed for posing the arm, used ITS LateUpdate function to set the angle, AND added the line above to alter its default execution order.

    This solved most of the problems, but there was one more: I had included the sprites' angles in my array of things to set the angle on. For some reason, this was messing with the position of the sprite and/or its bones. It is important, when using this technique, to ONLY modify bone angles, not sprite angles. Otherwise you find the separate bits come adrift from where they are supposed to be.

    Still can't get IK to work, but I don't think I need it now as this is a very simple game.