Rotating Input to Match Rotating Camera

Godot Version

4.2.1

Question

I am doing a mix of using Godot’s default CharacterBody3D movement script and following this video tutorial.

The script worked great until my line 26. I get the error “Too many arguments for “rotated()” call. Expected at most 1 but received 2.” The problem I’m having is that I get the 3rd person rotating camera I wanted, I get the model changing which way they’re facing, but I cannot rotate the input values to match what the SpringArm3D and Camera3D are doing.

The tutorial is on an old version, so has the way to find rotation changed? The error itself says I should have one argument, but the docs seem to say it required a vector AND an angle. Any hints?

extends CharacterBody3D


const SPEED = 5.0
const JUMP_VELOCITY = 4.5

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")

@onready var _spring_arm: SpringArm3D = $SpringArm3D
@onready var model: Node3D = $RobotArmature


func _physics_process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y -= 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", "forward", "back")
	**input_dir = input_dir.rotated(Vector3.UP, _spring_arm.rotation.y).normalized()**

	
	var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	if direction:
		velocity.x = direction.x * SPEED
		velocity.z = direction.z * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)

	move_and_slide()
	
	if velocity.length() > 0.2:
		var look_direction = Vector2(velocity.z, velocity.x)
		model.rotation.y = look_direction.angle()
	
func _process(_delta: float) -> void:
	_spring_arm.position = position

Input.get_vector() returns a Vector2.
According to the documentation of 4.2, Vector2.rotated() takes only a single argument. See here:

Is it possible, that you have confused it with the description of Vector3.rotated()?

1 Like

It looks to me like Sauermann is correct about the issue, and that your code ought to work if you revised it like so:

var input_vector = Input.get_vector("left", "right", "forward", "back")
var input_dir = Vector3.new(input_vector.x, 0, input_vector.z)
input_dir = input_dir.rotated(Vector3.UP, _spring_arm.rotation.y).normalized()
1 Like

Oooohhh, that explanation makes sense. But if Input.get_vector() is only going to return an X and Y, input_vector.z is not ever going to be populated, right?

That code didn’t work because Godot isn’t recognizing the word “new”. The game crashes. If I take the word new out, it says “Invalid get index ‘z’ (on bsae: ‘Vector2’).”

Ahh, my bad. I’m pretty new to Godot myself. I think this would do it (I forgot that Vector3 doesn’t need a new in GDScript and I typo’d input_vector.y as input_vector.z) -

var input_vector = Input.get_vector("left", "right", "forward", "back")
var input_dir = Vector3(input_vector.x, 0, input_vector.y)
input_dir = input_dir.rotated(Vector3.UP, _spring_arm.rotation.y).normalized()
1 Like

This fixed the errors! Then I had a small issue where I lost Z directional movement, but I fixed it and it worked!!! Here’s the code in case it helps anyone:

extends CharacterBody3D


const SPEED = 5.0
const JUMP_VELOCITY = 4.5

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")

@onready var _spring_arm: SpringArm3D = $SpringArm3D
@onready var model: Node3D = $RobotArmature


func _physics_process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y -= 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_vector = Input.get_vector("left", "right", "up", "down")
	var input_dir = Vector3(input_vector.x, 0, input_vector.y)
	input_dir = input_dir.rotated(Vector3.UP, _spring_arm.rotation.y).normalized()

	
	var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.z)).normalized()
	if direction:
		velocity.x = direction.x * SPEED
		velocity.z = direction.z * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)

	move_and_slide()
	
	if velocity.length() > 0.2:
		var look_direction = Vector2(velocity.z, velocity.x)
		model.rotation.y = look_direction.angle()
	
func _process(_delta: float) -> void:
	_spring_arm.position = position
1 Like

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