# Limit rotation of bone in gdscript

4.2.1

### Question

I’m making an open source 3d fps game, and replacing a capsule with a 3d model, the problem I’m having is I can’t find a reliable way to keep the bone from rotating in the x axis too far.
repo

### Code

``````func _input(event):
if event is InputEventMouseMotion:
# Get the current pose of the bone
var bonePose = skel.get_bone_global_pose(17)
# Save the original position
var original_position = bonePose.origin
# Define the rotation axis as the X axis
var axis = Vector3(1, 0, 0)
# Define the rotation angle based on relative.x
angle = event.relative.y * mouse_sensitivity * VERTICAL_sensitivity
# Apply the rotation to the pose
bonePose = bonePose.rotated(axis, angle)
# Reset the position to the original one
bonePose.origin = original_position
# Set the new pose of the bone
skel.set_bone_global_pose_override(17, bonePose, 1.0, true)
``````
1 Like

The issue seems to be that you’re clamping the input but not the result. So it’s clamping how far it can move in a single frame, but not overall.

Instead, I’d suggest using an accumulator (just a float you add to or subtract from when you move the mouse), clamping the accumulator, and then using that to lerp between the two angles you want.

2 Likes

ok how would you do that?

``````accum += event.relative.x * scalar
accum = clampf(accum,0.,1.)
var angle = lerp_angle(angle_a, angle_b, accum)
skel.set_bone_pose_rotation(17, Quaternion(axis, angle))
``````

I don’t quite get how to use your code but I did figure it out.
here’s what I ended up with

``````func _input(event):
if event is InputEventMouseMotion:
# Get the current pose of the bone
var bonePose = skel.get_bone_global_pose(17)
# Save the original position
var original_position = bonePose.origin
# Define the rotation axis as the X axis
var axis = Vector3(1, 0, 0)
# Define the rotation angle based on relative.x
angle = event.relative.y * mouse_sensitivity * VERTICAL_sensitivity
# Apply the rotation to the pose
bonePose = bonePose.rotated(axis, angle)
# Changes the basis to a euler
var bonePosEuler = bonePose.basis.get_euler()
# Clamps that euler
bonePosEuler.x = clamp(bonePosEuler.x,-0.671,0.265)
# Turns the euler into a bias
bonePose.basis = Basis().from_euler(bonePosEuler)
# Reset the position to the original one
bonePose.origin = original_position
# Set the new pose of the bone
skel.set_bone_global_pose_override(17, bonePose, 1.0, true)

``````
2 Likes

Awesome! You did it without an accumulator, and that way works just fine too.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.