Godot Version
4.3
Question
Hey there folks,
I’m trying to build a 1st person character controller, after trying to experiment with adding sliding then trying to manually go back, I seem to have totally messed up my collision detection.
My character crouches, jumps, and moves, but horizontal collision is broken on objects that would stop the character standing should they be under it.
If anyone could take a look and maybe explain to me where I’ve gone wrong, I’d really appreciate it!
My Node Strcuture is:
extends CharacterBody3D
#Player Nodes
@onready var head = $"Neck/Head"
@onready var standing_collision_shape = $CollisionShapeWalking
@onready var crouching_collision_shape = $CollisionShapeCrouching
@onready var raycast3d = $RayCast3D
@onready var torch = $"Neck/Head/Player Torch"
# Speed Variables
var current_speed = 5.0
const walking_speed = 5.0
const sprinting_speed = 8.7
const crouching_speed = 2.0
const sliding_speed = 50.0
#States
var walking = false
var sprinting = false
var crouching = false
var free_looking = false
var sliding = false
# State Variables
# Head Height Variables
const walk_head_height = 1.8
const sprint_head_height = 1.6
const crouch_head_height = 1.3
const slide_head_height = 1.2
# Movement Functions
# Gradually change values instead of instantly snapping (walk to run etc)
var lerp_speed = 10.0
# Torch Variable Declaration
var torch_on = false # Declare once at the top
# Movement
const jump_velocity = 10.5
var crouching_depth = -0.5
# Camera
const mouse_sens = 0.04
var direction = Vector3.ZERO
# Movement Functions
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
# Initialize collision shapes
standing_collision_shape.disabled = false
crouching_collision_shape.disabled = true
head.position.y = walk_head_height
# Torch Toggle
# Mouse Movement and Rotation Lock
func _input(event: InputEvent):
if event is InputEventMouseMotion:
rotate_y(deg_to_rad(-event.relative.x * mouse_sens))
head.rotate_x(deg_to_rad(-event.relative.y * mouse_sens))
head.rotation.x = clamp(head.rotation.x, deg_to_rad(-98), deg_to_rad(90))
if Input.is_action_just_pressed("torch"):
print("torch button pressed")
torch_on = !torch_on # Toggle the state
torch.visible = torch_on # Set visibility based on toggle
# Switching Movement Speed
func _physics_process(delta):
if Input.is_action_pressed("crouch"):
# Force crouch when button is pressed
current_speed = crouching_speed
head.position.y = lerp(head.position.y, crouch_head_height, delta * lerp_speed)
standing_collision_shape.disabled = true
crouching_collision_shape.disabled = false
walking = false
sprinting = false
crouching = true
elif !raycast3d.is_colliding():
# Force crouch when there's an obstacle above
head.position.y = lerp(head.position.y, walk_head_height, delta * lerp_speed)
standing_collision_shape.disabled = true
crouching_collision_shape.disabled = false
if Input.is_action_pressed("sprint"):
current_speed = sprinting_speed
standing_collision_shape.disabled = false
crouching_collision_shape.disabled = true
walking = false
sprinting = true
crouching = false
else:
current_speed = walking_speed
head.position.y = lerp(head.position.y, walk_head_height, delta * lerp_speed)
standing_collision_shape.disabled = false
crouching_collision_shape.disabled = true
walking = true
sprinting = false
crouching = false
# Add the gravity.
if not is_on_floor():
velocity += get_gravity() * (delta + 0.025)
# 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.
var input_dir = Input.get_vector("left", "right", "forward", "backward")
direction = lerp(direction,(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),delta*lerp_speed)
if direction:
velocity.x = direction.x * current_speed
velocity.z = direction.z * current_speed
else:
velocity.x = move_toward(velocity.x, 0, current_speed)
velocity.z = move_toward(velocity.z, 0, current_speed)
move_and_slide()
------