- Edited
I have a problem with orientation and direction.
This is the code for movement:
func _physics_process(delta: float) -> void:
# Main movements
var input_dir: = Input.get_vector("move_left", "move_right", "move_up", "move_down")
var direction: = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
In the first GIF image I have the result I want: I'm rotating the camera around my character as he moves.
(but with the problem of inverted commands when I move back.)
In the second GIF, I solve the problem of inverted commands
(but every time I move the mouse the character follows the rotation, i dont want this).
@onready var playerbase_mount: = $PlayerBaseMount as Node3D
var direction: = (playerbase_mount.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
Who can help me to solve the situation?
Thanks.
[UPDATE] Here the final solution:
extends CharacterBody3D
#Basis variables
@onready var visuals_basis: Basis = global_transform.basis
@onready var right_direction: = Vector3.RIGHT
@onready var front_direction: = Vector3.FORWARD
@onready var player_speed: = 3
@onready var player_is_free: = false
func _physics_process(delta: float) -> void:
# Main movements
var input_dir: = Input.get_vector("move_left", "move_right", "move_up", "move_down")
if not is_on_floor(): velocity.y -= 12.0 * delta
# Mesh movements
var visuals_rotation: = player_speed * 3
if input_dir.length_squared() > 0.9 and is_on_floor():
visuals_basis.z = (-input_dir.x * right_direction + -input_dir.y * front_direction).normalized()
visuals_basis.y = Vector3.UP.normalized()
visuals_basis.x = visuals_basis.y.cross(visuals_basis.z)
visuals_basis = visuals_basis.orthonormalized()
global_transform.basis = global_transform.basis.slerp(visuals_basis, visuals_rotation * delta).orthonormalized()
# Direction and velocity
var _move_and_slide = move_and_slide()
if player_is_free:
if is_on_floor():
velocity = (right_direction * input_dir.x + front_direction * input_dir.y) * player_speed
else:
player_is_free = false
velocity.x = move_toward(velocity.x,0, player_speed)
velocity.z = move_toward(velocity.z,0, player_speed)
# Input-follow camera
func _input(event: InputEvent) -> void:
# reference to node3d on camera's scene
var playerbase_mount: = get_parent().get_node("PlayerBaseMount") as Node3D
if event is InputEventKey:
if event.is_pressed() and not event.is_echo():
var camera_fix_direction: = playerbase_mount.global_transform.basis.orthonormalized()
right_direction = camera_fix_direction.x.normalized()
front_direction = Vector3(camera_fix_direction.z.x, 0.0, camera_fix_direction.z.z).normalized()
(PlayerbaseMount) Camera in separate scene with this script:
extends Node3D
@onready var playerbase_spring: = $PlayerBaseSpring as SpringArm3D
@onready var camera_is_free: = false
@onready var mouse_sensitivity: = 0.5
func _ready() -> void:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _process(_delta: float) -> void:
# reference to node3d on player's tree structure placed on its neck
var player: = get_parent().get_child(0).get_node("PlayerBaseLookAt")
global_position = (player as Node3D).global_position
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion && Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
if camera_is_free:
rotate_y(deg_to_rad( - (event as InputEventMouseMotion).relative.round().x * mouse_sensitivity))
playerbase_spring.rotate_x(deg_to_rad( - (event as InputEventMouseMotion).relative.round().y * mouse_sensitivity))
playerbase_spring.rotation.x = clampf(playerbase_spring.rotation.x, -PI/4, PI/4)
playerbase_spring.rotation.z = clampf(playerbase_spring.rotation.y, -PI/4, PI/4)