Help with character movement when rotating camera in isometric game

Godot Version

4.3

Question

Hi! I have an issue with character movement that’s got me at a complete loss. I’m making a game in 3D, however the camera is orthographic and up in the sky at a 45 degree angle to give the feel of a 2D isometric game. Everything works as expected with regards to character movement except one issue. When I rotate the camera, I rotate the character as well, however the direction the character moves doesn’t update to match their rotation.

For instance, if I rotate the camera 90 degrees to the left, the character rotates along with it (so you’re still looking at their back), but when pressing the “up” input action, the character is now moving right. I’d expect the character to move away from the camera as they would with the default transform. Hope this is clear enough. Here’s a screenshot of the game currently:

The parent of the camera is a Node3D called CameraPivot that handles rotation. Here’s its attached script:

extends Node3D

@onready var player: CharacterBody3D = get_tree().get_nodes_in_group("PlayerCharacter")[0]
@onready var sky_camera: Camera3D = $SkyCamera
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	# Handle camera rotation
	if Input.is_action_pressed("rotate_camera_left"):
		rotation_degrees.y -= 1
		player.rotation_degrees.y -= 1
		
	if Input.is_action_pressed("rotate_camera_right"):
		rotation_degrees.y += 1
		player.rotation_degrees.y += 1

func _input(event: InputEvent) -> void:
	if Input.is_action_just_pressed("zoom_in"):
		if sky_camera.size > 5:
			sky_camera.size -= 1
			
	if Input.is_action_just_pressed("zoom_out"):
		if sky_camera.size < 100:
			sky_camera.size += 1
`

And then the script for the player character:

`
extends CharacterBody3D

@onready var camera_pivot = get_tree().get_nodes_in_group("PlayerCharacter")[1]
@export var _rotation_speed : float = TAU

const SPEED = 5.0
const JUMP_VELOCITY = 4.5
var _theta : float


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("jump") 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_right", "move_left", "move_down", "move_up")
	var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	if direction:
		# Handle character rotation to look in the direction of movement
		_theta = wrapf(atan2(input_dir.x, input_dir.y) - rotation.y, -PI, PI)
		rotation.y += clamp(_rotation_speed * delta, 0, abs(_theta)) * sign(_theta)
		# Movement is 3D, sure, but we treat it as if it's 2D so as not to bork rotation etc.
		# Otherwise, when character rotates, velocity is relative to how they're facing
		velocity.x = input_dir.x * SPEED
		velocity.z = input_dir.y * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)

	move_and_slide()

I guess my question boils down to:

How can I update the direction that my character sees as “up” when rotating the camera?

Any help is massively appreciated, thanks for reading!

Hi,

_theta = wrapf(atan2(input_dir.x, input_dir.y) - rotation.y, -PI, PI)
		rotation.y += clamp(_rotation_speed * delta, 0, abs(_theta)) * sign(_theta)

You are rotating your CharacterBody3D with your input, it seems, but then :

func _process(delta: float) -> void:
	# Handle camera rotation
	if Input.is_action_pressed("rotate_camera_left"):
		rotation_degrees.y -= 1
		player.rotation_degrees.y -= 1 # ??

You’re rotating it again with your camera controls.

What happens if you remove those two lines ? ( 13 & 17)

1 Like

Hi haptik!

Thanks, but that first block of code makes the player character rotate to look in the direction they’re moving. The second one is my best try at making them follow the camera’s rotation i.e. if you rotate the camera 90 degrees left, the player character rotates 90 degrees left.

However if you do so, pressing the “up” input (i.e. key W) causes the player to move in the direction that would have originally been up.

Here’s the repo if you’d like to clone and see what I mean:

Repository

Thanks!

Also forgot to mention, if I remove those two lines the player simply doesn’t rotate with the camera pivot, doesn’t change the issue I’m facing

Hi,

I just tried your project and it seems like you fixed it or am I wrong ?

The character is following the the rotation of the camera while going in the direction the camera is pointing at. If it is not, I am sorry but there’s something I am missing to understand what you are willing to do.

Hi Haptik,

Apologies, I had a surgery and wasn’t able to reply but yes, I seem to have found the fix. I have a few more issues to work through but for now I’m going to mark your first post as the resolution for anyone who stumbles on this in the future. Thanks for the help!

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