How Do I rotate my 3d player in a top-down rpg view system?

Godot Version

4.2.1

Question

I want my character to move and rotate using only the WASD buttons. I tried using
var lookdir = atan2(-direction.x, -direction.y)
body.rotation.y = lookdir
but this only moves the player for as long as I press buttons and resets all rotations when I release the buttons. I want the rotation to be permanent when I move in a certain direction. Like when the Idle animation plays I want the player to face the direction he last moved towards. But I don’t know how to. I’ve been scrolling through tutorials and QNA’s and I found look_at-inputdirection) should work but it gives weird results like the entire playerbody just rotates including the camera and it swings from left to right in a weird way. Here’s my player script :

extends CharacterBody3D

#basic physics
var speed = 5
var can_attack = true
var gravity = -2
var sword_damage = 6

#combo
var current_combo = 1

@onready var timer = $Timer
@onready var hitbox = $hitbox
@onready var anim_player = $AnimationPlayer
@onready var healthbar = $“…/ENemy/SubViewport/healthbar”
@onready var enemy = $“…/ENemy”
@onready var body = $body

@onready var enemy_animation_player = $“…/ENemy/AnimationPlayer”

func attack():

var enemies = hitbox.get_overlapping_bodies()
for Enemy in enemies: 
	if Enemy.is_in_group("Enemy"): #and can_attack == true : 
		
		Enemy.takedamage()
		healthbar.value -= sword_damage		

func _physics_process(delta):

#movement
if is_on_floor():
var inputdirection = Input.get_vector(“left”, “right” , “forward”, “backward”)
var direction = (transform.basis * Vector3(inputdirection.x, 0 , inputdirection.y).normalized())

	velocity = direction * speed
	
	
	if Input.is_action_just_pressed("sprint"):
		speed = 10	 
	
	if Input.is_action_just_released("sprint"):
		speed = 5
	
	if Input.is_action_just_pressed("alt") and current_combo == 1:
		
		attack()			
		anim_player.play("attack1")
		current_combo = 2
	elif Input.is_action_just_pressed("alt") and current_combo == 2:
			
		attack()
		anim_player.play("attack2")
		current_combo = 1
				
	
	
move_and_slide()

#airborne
if not is_on_floor():
velocity.y = gravity

#func _on_animation_player_animation_finished(anim_name):
func _on_enemyrange_body_exited(body):
enemy.animation_player.play(“idle”)

Easiest fix would be to add if not direction.is_zero_approx(): before var lookdir and body.rotation lines

1 Like