0 votes

We have our player with cutout animation, and it uses inverse kinematics and bones for the limbs. Particularly, we are looking at the arms here.

We are attempting to add aiming to the gun. When facing to the right and aiming, it looks great. When facing to the left, however, it gets wonky and the arms don't match up at all.

We are setting the parent Body sprite.scale.x to -1 when the player turns to the left. Tested it out in the editor and this works as expected.

For some reason, the rotations applied get messed up due to the flipping.

Code below:

var rotation_offsets
var transforms

Place player hands on Position2Ds on gun

func place_hand(base_node, ik_node, is_front):
    transforms = []
    rotation_offsets = []
    var target = front_hand_position if is_front else back_hand_position
    _calc_ik(base_node, ik_node, target, true)
    _apply_ik(base_node, ik_node)

calculate

  func _calc_ik(node, ik_node, target_node, is_forward, index = 0):
        var length = 0
        var target = null
        transforms.append(null)
        rotation_offsets.append(null)
        if node.get_child_count() > 0 and node != ik_node:
            target = node.get_child(0).global_position
            rotation_offsets[index] = node.get_child(0).position.angle()
            length = (target - node.global_position).length()
            _calc_ik(node.get_child(0), ik_node, target_node, is_forward, index + 1)
        if node == ik_node:
            var rot = 0
            var pos = target_node.global_position
            transforms[index] = Transform2D(rot, pos)
        else:
            var rot = (transforms[index+1].get_origin() - node.global_position).angle()
            var pos = (transforms[index+1].get_origin() - (Vector2.RIGHT * length).rotated(rot))
            transforms[index] = Transform2D(rot, pos)

apply

func _apply_ik(node, ik_node, index = 0):
    if node != ik_node:
        var rotation_to_apply = transforms[index].get_rotation() - rotation_offsets[index]
        _apply_ik(node.get_child(0), ik_node, index + 1)
        node.global_rotation = rotation_to_apply
in Engine by (12 points)

Hi!
First, i'm courious about is_forward variable.. it seems to be always true, and never used.. is reserved for future use?
Second, i think the problem might be when rotating pos:

var pos = (transforms[index+1].get_origin() - (Vector2.RIGHT * length).rotated(rot))

I made a (more simple) aiming animation here and i had to add 180 when rotating if flipped.
I didn't go through all the ik chain, just rotated one part of the body, so idk if this apply to your case... but may be it helps.

Also, let me ask you if the gun is flipped with the body (as it is its child or something like that) or not.. cause rotation in gun seems to work fine.

or perhaps you should change the Vector2.RIGHT when flipped.

Tried the vector.RIGHT, that's just getting the normal though.

Here is a repo with the simplified version of the code that can be run in Godot. Left click for moving, and right click to process movement every tick. It mirrors the same IK chain.

enter link description here

Did you ever get this figured out? I'm attempting to the exact same thing now - aiming a gun in my character's hands using cutout animation, auto-gen bones, and IK. Any help you could give would be greatly appreciated.

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.