Align To Normal With Raycast Question

I eventually got it working using that method using the second and third parameters that you mentioned, but I opted a different approach with similar results. Based on this post here(credit). With some tweaking, it’s moving in all the proper directions, and feels great so far; and no weird crashes when I change the basis anymore. :sweat_smile:

The issue now is that it’s falling apart at the mesh level with how I’m rotating it since I chose to rotate the mesh like this:


	if Input.is_action_pressed("movement"):
		var dir = Input.get_vector("move_backward", "move_forward", "move_right", "move_left").normalized()
		dir = dir.rotated(player_camera.yaw_node.rotation.y)
		var target_rotation = atan2(dir.y, dir.x) - rotation.y
		mesh.rotation.y = lerp_angle(mesh.rotation.y, target_rotation, turn_speed * delta)
		translate(Vector3(-dir.y, 0, -dir.x) * move_speed * delta)

Video

Current Code So Far:

extends CharacterBody3D

@export var move_speed = 5.0
@export var jump_height = 5.0
@export var turn_speed = 5.0

@onready var wall_change_detection: RayCast3D = %WallChangeDetection

@onready var player_camera: PlayerCamera = $PlayerCamera
@onready var mesh: MeshInstance3D = $Mesh


var transitioning : bool = false


func _input(event: InputEvent) -> void:
	if event.is_action_pressed("interact") and not transitioning:
		if wall_change_detection.is_colliding():
			align_to_new_normal(wall_change_detection.get_collision_normal(), wall_change_detection.get_collision_point())


func _physics_process(delta: float) -> void:
	
	### Add the gravity.
	#if upright:
		#velocity.y += -5 * delta
	
	if Input.is_action_pressed("movement"):
		var dir = Input.get_vector("move_backward", "move_forward", "move_right", "move_left").normalized()
		dir = dir.rotated(player_camera.yaw_node.rotation.y)
		var target_rotation = atan2(dir.y, dir.x) - rotation.y
		mesh.rotation.y = lerp_angle(mesh.rotation.y, target_rotation, turn_speed * delta)
		translate(Vector3(-dir.y, 0, -dir.x) * move_speed * delta)
	
	move_and_slide()

func align_to_new_normal(new_normal:Vector3, attach_point:Vector3):
	transitioning = true
	var original = self.transform.basis.y
	var cosa = original.dot(new_normal)
	var alpha = acos(cosa)
	var axis = original.cross(new_normal)
	axis = axis.normalized()
	
	var t = get_tree().create_tween()
	
	t.tween_property(self, "transform", self.transform.rotated(axis, alpha), 0.2)
	t.parallel().tween_property(self, "global_position", wall_change_detection.get_collision_point(), 0.2)
	t.tween_callback(func(): transitioning = false)