AnimationTree overriding rotation

Godot Version

4.3

Question

I am new to Godot, like really new so excuse me.
I am trying to set up a third person character controller. The Problem I’m facing right now is that the animation tree (more precisely the blend2D) seems to be overwriting the rotation of my character, which i update based on the WASD inputs of the player. It does work with the AnimationTree inactive, but not if it is active. I followed some tutorials and none ran into this problem.

here is my Character script

extends CharacterBody3D

const SPEED = 15.0
const JUMP_VELOCITY = 4.5
const LERP_VAL = 0.15

@onready var armature = $Armature
@onready var spring_arm_pivot = $CameraController
@onready var anim_tree = $AnimationTree

func _unhandled_input(event: InputEvent) → void:
if Input.is_action_just_pressed(“quit”):
get_tree().quit()

func _physics_process(delta: float) → void:
armature.rotation.y = lerp_angle(armature.rotation.y, atan2(velocity.x, velocity.z), LERP_VAL)
anim_tree.set_active(true)
anim_tree.set(“parameters/Movement/blend_position”, Vector2(-velocity.x, -velocity.z))

# Add the gravity.
if not is_on_floor():
	velocity += get_gravity() * delta

# Handle jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
	velocity.y = JUMP_VELOCITY


# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var input_dir := Input.get_vector("left", "right", "forwards", "backwards")
var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
direction = direction.rotated(Vector3.UP, spring_arm_pivot.rotation.y)
if direction:
	velocity.x = lerp(velocity.x, direction.x * SPEED, LERP_VAL)
	velocity.z = lerp(velocity.z, direction.z * SPEED, LERP_VAL)
	
	
else:
	velocity.x = lerp(velocity.x, 0.0, LERP_VAL)
	velocity.z = lerp(velocity.z, 0.0, LERP_VAL)
	




move_and_slide()

Is this just a problem with importing animations that themselves modify rotation?

(unfortunately i cannot upload a vid of what i mean but i think you get the rough idea)

If you are animating the rotation property of the armature then you have two systems fighting, you could child the armature, let it animate and rotate it’s parent.

Ah okay. I was thinking something similar, but Just wasnt sure of it. So id create a new node3d and parent the Armature to it?

I have done what i think you mean but ran into another problem. I have created another node so that my player scene looks like this:

Characterbody3D
AnimPlayer
AnimTree
CollisionShape3D
Node3D
–>Armature
---->Skeleton3D

when i do this and adjust the previously posted code so that var armature has the right path it does turn with the inputs but now it doesnt play the animations as well. After some research, could it be that I need to update the path of the AnimationPlayer?

1 Like

You will have to update the Animation Player/Animation Tree’s “Root Node”

1 Like

Hello! I am here with the same issue but this solution didn’t work for me.

I added my armature as a child of a new Node3D, and I eventually figured out how to update the animation player/animation tree’s root node as suggested by @gertkeno.

But it didn’t seem to work and I was just getting weird warnings about “animation mixer couldn’t resolve track” etc. To solve this I reimported my animation as a parent of an empty called “Node3D” from blender and deleted my old character scene to start fresh.

I am now exactly where @gertkeno seems to have solved the original problem with no warnings but my armature will only rotate if my animation tree is inactive again, so back at square one!

I have tried another solution from a seperate thread where the solution was to deactivate the animation tree in the Inspector and set it to active at runtime with “func _ready():” - this did not work either.

I am following a tutorial and my code looks identical to @twise 's original code. Makes me think we are following the same tut. So I know this is supposed to work.

I really hope someone can help. This seems like such a dumb bug especially as it seems like pretty standard process for achieving this effect.

Can you show your script rotation and/or scene tree?

1 Like

Here is the script from my character:

extends CharacterBody3D

@onready var armature = $Node3D/Armature
@onready var spring_arm_pivot = $SpringArmPivot
@onready var spring_arm = $SpringArmPivot/SpringArm3D
@onready var anim_tree = $AnimationTree

const SPEED = 5.0
const JUMP_VELOCITY = 4.5
const LERP_VAL = .2

func _ready():
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
	
	anim_tree.set_active(true)

func _unhandled_input(event):
	if Input.is_action_just_pressed("action_quit"):
		get_tree().quit()
	
	if event is InputEventMouseMotion:
		spring_arm_pivot.rotate_y(-event.relative.x * .005)
		spring_arm.rotate_x(-event.relative.y * .005)
		spring_arm.rotation.x = clamp(spring_arm.rotation.x, -PI/4, PI/4)
	
func _physics_process(delta: float) -> void:
	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta

	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var input_dir := Input.get_vector("move_left", "move_right", "move_forward", "move_back")
	var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	direction = direction.rotated(Vector3.UP, spring_arm_pivot.rotation.y)
	if direction:
		velocity.x = lerp(velocity.x, direction.x * SPEED, LERP_VAL)
		velocity.z = lerp(velocity.z, direction.z * SPEED, LERP_VAL)
		armature.rotation.y = lerp_angle(armature.rotation.y, atan2(-velocity.x, -velocity.z), LERP_VAL)
	else:
		velocity.x = lerp(velocity.x, 0.0 * SPEED, LERP_VAL)
		velocity.z = lerp(velocity.z, 0.0 * SPEED, LERP_VAL)
		
	anim_tree.set("parameters/BlendSpace1D/blend_position", velocity.length() / SPEED)
		
	move_and_slide()

Here is a screenshot of my scene tree:

image

Really bugging me this one. Thanks for taking a look!

Hey there! I did eventually figure it out myself with my project. The thing that might be the problem here is that in your code you are still trying to rotate the armature (armature.rotation.y). Instead try it with your node3D, the parent of the armature. That should probably solve it.

2 Likes

Worked a treat, thanks very much!

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