Godot Version
godot-4
Question
I have a first person game where I’m trying to make it so that a player can sprint up steep slopes, but when they try to walk, they slide down the slope. I’ve tested setting the Floor_Max_Angle variable via code, but that seems to make it so that the player sticks to any slope, including ceilings. Is there an established way to set this variable through code effectively?
here’s my code. It’s attatched toa character body3d, which has a capsule collider as a child. there’s a “head” pivot which is the parent of the camera, and those are used in tandem to control the view angle
extends CharacterBody3D
var speed
const WALK_SPEED = 2.0
const SPRINT_SPEED = 7.0
const JUMP_VELOCITY = 4.5
const SENSITIVITY = 0.03
const BOB_FREQUENCY = 2.0
const BOB_AMPLITUDE = 0.08
var t_bob = 0.0
const BASE_FOV = 100.0
const FOV_CHANGE = 1.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 head = $head
@onready var camera = $head/Camera3D
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _unhandled_input(event):
if event is InputEventMouseMotion:
head.rotate_y(-event.relative.x * SENSITIVITY)
camera.rotate_x(-event.relative.y * SENSITIVITY)
camera.rotation.x = clamp(camera.rotation.x, deg_to_rad(-89), deg_to_rad(90))
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
if Input.is_action_pressed("Sprint"):
speed = SPRINT_SPEED
else:
speed = WALK_SPEED
# 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")
var direction = (head.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if is_on_floor():
if direction:
velocity.x = direction.x * speed
velocity.z = direction.z * speed
else:
velocity.x = lerp(velocity.x, direction.x * speed, delta *7.0)
velocity.z = lerp(velocity.z, direction.z * speed, delta *7.0)
else:
velocity.x = lerp(velocity.x, direction.x * speed, delta *3.0)
velocity.z = lerp(velocity.z, direction.z * speed, delta *3.0)
#headbob
t_bob += delta * velocity.length() * float(is_on_floor())
camera.transform.origin = _headbob(t_bob)
var velocity_clamped = clamp(velocity.length(), 0.5,SPRINT_SPEED*2)
var target_fov = BASE_FOV + FOV_CHANGE * velocity_clamped
camera.fov = lerp(camera.fov, target_fov, delta * 8.0)
move_and_slide()
func _headbob(time) -> Vector3:
var pos = Vector3.ZERO
pos.y = sin(time * BOB_FREQUENCY) * BOB_AMPLITUDE
pos.x = cos(time * BOB_FREQUENCY/2) * BOB_AMPLITUDE
return pos