Godot Version
v4.2.2.stable.official [15073afe3]
Question
I am trying to create my first 3D game using Godot. I have some experience programming in other languages and using other game engines for 2D games. This game will be a very simple third person game. To keep things encapsulated I have created a player scene and a camera scene which are siblings in the main game scene. I use an export variable to set the player as a target for the camera. The camera script handles all the logic for looking around with the mouse and following the target. Now I want to be able to rotate the player when pressing the forward key into the direction of the camera however I am not sure the best way to access the camera transform without hardcoding a reference to it.
The camera scene is structured as SpringArm3D > Camera3D
Camera Script
extends SpringArm3D
@export var target: CharacterBody3D
@export var target_offset: Vector3 = Vector3.ZERO
# Store the camera rotation.
var pitch: float = 0.0
var yaw: float = 0.0
func _ready() -> void:
# Prevent the spring arm from colliding with the target.
add_excluded_object(target)
# Capture the mouse.
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _unhandled_input(event) -> void:
if event is InputEventMouseMotion:
# Change the pitch while keeping the angle between min and max.
pitch -= event.relative.y * 0.1
pitch = clamp(pitch, -90.0, 30.0)
# Change the yaw while wrapping the angle between 0 and 360.
yaw -= event.relative.x * 0.1
yaw = wrapf(yaw, 0.0, 360.0)
# Set camera transform basis.
transform.basis = Basis()
rotate_x(deg_to_rad(pitch))
rotate_y(deg_to_rad(yaw))
func _physics_process(delta) -> void:
# Follow the target.
transform.origin = target.transform.origin + target_offset
The player script is currently just the default CharacterBody3D script:
Player Script
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")
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("ui_left", "ui_right", "ui_up", "ui_down")
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()
One way I thought of doing this was to set the camera SpringArm3D node as top level, then in the player scene add the camera scene as a child. Then I would access the camera transform using the unique name accessor. This feels a bit janky and I would rather keep the camera and player separated if at all possible. I have also read about RemoteTransform3D in the documentation. Would it be possible to somehow transmit the camera transform to the player using this?