Heya, title explains everything. I wanna align the player with the floor he’s walking on while not affecting movement direction. I tried looking up online but most posts on these forums regarding this issue always just have an old Godot 3.0 tutorial as the solution, which is not what I want. Please help me with this.
Movement script:
extends CharacterBody3D #-@onready-----------------------------@onready----------------------------------------------- @onready var Character := $Character @onready var Camera := $SpringArm3D/Camera3D var Current_Speed := 0.0 var Accel_Rate := (Constants.Max_Speed - Constants.Min_Speed) / Constants.Accel_Time var Speed_Stop_Timer := 0.0 var Jump_HoldTime := 0.0 #------------------------------------------------------------------------------- func _physics_process(delta: float) → void: if not is_on_floor(): if Input.is_action_pressed(“Jump”) and Jump_HoldTime > 0.0: velocity.y -= Constants.Gravity * 0.5 * delta Jump_HoldTime -= delta else: velocity.y -= Constants.Gravity * delta else: velocity.y = -0.1 #------------------------------------------------------------------------------- if Input.is_action_pressed(“Jump”) and is_on_floor(): Jump_HoldTime = Constants.Max_JumpHoldTime #------------------------------------------------------------------------------- velocity.y = Constants.Jump_Velocity #------------------------------------------------------------------------------- var Input_Direction = Input.get_vector(“MoveLeft”, “MoveRight”, “MoveBackward”, “MoveForward”) #------------------------------------------------------------------------------- var Camera_Basis = Camera.global_basis var Forward = -Camera_Basis.z var Right = Camera_Basis.x #------------------------------------------------------------------------------- Forward.y = 0 Right.y = 0 #------------------------------------------------------------------------------- Forward = Forward.normalized() Right = Right.normalized() #------------------------------------------------------------------------------- var Direction = (Forward * Input_Direction.y + Right * Input_Direction.x).normalized() #------------------------------------------------------------------------------- if Direction.length() > 0: var Target_Angle = atan2(Direction.x, Direction.z) var Angle_Diff = abs(wrapf(Target_Angle - Character.rotation.y, -PI, PI)) #------------------------------------------------------------------------------- if Angle_Diff > deg_to_rad(150): Current_Speed *= 0.625 #------------------------------------------------------------------------------- var Turn_Speed = lerp(8.0, 20.0, Angle_Diff / PI) #------------------------------------------------------------------------------- if Input_Direction.y > 0: Turn_Speed *= 1.5 #------------------------------------------------------------------------------- Character.rotation.y = lerp_angle(Character.rotation.y, Target_Angle, Turn_Speed * delta) #------------------------------------------------------------------------------- if Direction.length() > 0: Speed_Stop_Timer = 0.0 #------------------------------------------------------------------------------- Current_Speed += Accel_Rate * delta Current_Speed = clamp(Current_Speed, Constants.Min_Speed, Constants.Max_Speed) #------------------------------------------------------------------------------- velocity.x = Direction.x * Current_Speed velocity.z = Direction.z * Current_Speed else: Speed_Stop_Timer += delta #------------------------------------------------------------------------------- var Stop_Rate = Accel_Rate * 14.0 var Horizontal_Velocity = Vector3(velocity.x, 0, velocity.z) #------------------------------------------------------------------------------- Horizontal_Velocity = Horizontal_Velocity.move_toward(Vector3.ZERO, Stop_Rate * delta) #------------------------------------------------------------------------------- velocity.x = Horizontal_Velocity.x velocity.z = Horizontal_Velocity.z #------------------------------------------------------------------------------- if Speed_Stop_Timer >= Constants.Stop_Speed_Reset_Time: Current_Speed = 0.0 #------------------------------------------------------------------------------- move_and_slide()
extends CharacterBody3D
#-------------------------------------------------------------------------------
@onready var Character := $Character
@onready var Camera := $SpringArm3D/Camera3D
var Current_Speed := 0.0
var Accel_Rate := (Constants.Max_Speed - Constants.Min_Speed) / Constants.Accel_Time
var Speed_Stop_Timer := 0.0
var Jump_HoldTime := 0.0
#-------------------------------------------------------------------------------
func _physics_process(delta: float) -> void:
if not is_on_floor():
if Input.is_action_pressed("Jump") and Jump_HoldTime > 0.0:
velocity.y -= Constants.Gravity * 0.5 * delta
Jump_HoldTime -= delta
else:
velocity.y -= Constants.Gravity * delta
else:
velocity.y = -0.1
#-------------------------------------------------------------------------------
if Input.is_action_pressed("Jump") and is_on_floor():
Jump_HoldTime = Constants.Max_JumpHoldTime
#-------------------------------------------------------------------------------
velocity.y = Constants.Jump_Velocity
#-------------------------------------------------------------------------------
var Input_Direction = Input.get_vector("MoveLeft", "MoveRight", "MoveBackward", "MoveForward")
#-------------------------------------------------------------------------------
var Camera_Basis = Camera.global_basis
var Forward = -Camera_Basis.z
var Right = Camera_Basis.x
#-------------------------------------------------------------------------------
Forward.y = 0
Right.y = 0
#-------------------------------------------------------------------------------
Forward = Forward.normalized()
Right = Right.normalized()
#-------------------------------------------------------------------------------
var Direction = (Forward * Input_Direction.y + Right * Input_Direction.x).normalized()
#-------------------------------------------------------------------------------
if Direction.length() > 0:
var Target_Angle = atan2(Direction.x, Direction.z)
var Angle_Diff = abs(wrapf(Target_Angle - Character.rotation.y, -PI, PI))
#-------------------------------------------------------------------------------
if Angle_Diff > deg_to_rad(150):
Current_Speed *= 0.625
#-------------------------------------------------------------------------------
var Turn_Speed = lerp(8.0, 20.0, Angle_Diff / PI)
#-------------------------------------------------------------------------------
if Input_Direction.y > 0:
Turn_Speed *= 1.5
#-------------------------------------------------------------------------------
Character.rotation.y = lerp_angle(Character.rotation.y, Target_Angle, Turn_Speed * delta)
#-------------------------------------------------------------------------------
if Direction.length() > 0:
Speed_Stop_Timer = 0.0
#-------------------------------------------------------------------------------
if is_on_floor():
Current_Speed += Accel_Rate * delta
else:
Current_Speed += lerp(Current_Speed, 20.0, 0.5 * delta)
Current_Speed = clamp(Current_Speed, Constants.Min_Speed, Constants.Max_Speed)
#-------------------------------------------------------------------------------
velocity.x = Direction.x * Current_Speed
velocity.z = Direction.z * Current_Speed
else:
Speed_Stop_Timer += delta
#-------------------------------------------------------------------------------
var Stop_Rate = Accel_Rate * 14.0
var Horizontal_Velocity = Vector3(velocity.x, 0, velocity.z)
#-------------------------------------------------------------------------------
Horizontal_Velocity = Horizontal_Velocity.move_toward(Vector3.ZERO, Stop_Rate * delta)
#-------------------------------------------------------------------------------
velocity.x = Horizontal_Velocity.x
velocity.z = Horizontal_Velocity.z
#-------------------------------------------------------------------------------
if Speed_Stop_Timer >= Constants.Stop_Speed_Reset_Time:
Current_Speed = 0.0
#-------------------------------------------------------------------------------
move_and_slide()
And here’s the problem:
func _physics_process(delta: float) -> void:
if not is_on_floor():
if Input.is_action_pressed("Jump") and Jump_HoldTime > 0.0:
velocity.y -= Constants.Gravity * 0.5 * delta
Jump_HoldTime -= delta
else:
velocity.y -= Constants.Gravity * delta
else:
velocity.y = -0.1
Your gravity is not being applied consistently. This is how that same code is done in the default template.
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("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
Your LLM is way overcomplicating your code. Tell it to use get_gravity() instead of Constants.Gravity And if you want to change the default grravity constant, do it in Project Settings.
i did not use an llm, the reason the jump code is like this is because i want the jump to go higher depending on how long you hold the jump button. Although i did not know about get_gravity. But anyways that isn’t the issue, i’m trying to align the player with the surface he’s walking on
In that case you need to create a RacCast3D pointing straight down, and get collision data from it, and then used vector math to get a normal so that you can rotating the character opposite the angle of the floor.
CharacterBody3D already gives you the ground normal. So you could build a rotation matrix by doing something like this:
var up = Vector3.UP
if is_on_floor():
up = get_floor_normal()
var forward = -transform.basis.z.slide(up).normalized()
var right = forward.cross(up)
transform.basis = Basis(right, up, -forward)
And if you want a smooth rotation, you could replace the last line with:
var speed = 20
var alignment = Basis(right, up, -forward)
transform.basis = transform.basis.slerp(alignment, speed * delta)