extends RigidBody3D # Initially I used a CharacterBody3D, however, I wanted the player to bounce off # other objects in the environment and that would have required manual handling # of collisions. So that's why we're using a RigidBody3D instead. const MOVE_SPEED := 8.0 const ACCELLERATION := 30.0 const DECELLERATION := 40.0 const JUMP_SPEED := 4.0 @export var camera_path: NodePath @onready var cam: Camera3D = get_node(camera_path) if camera_path != NodePath("") else null func _ready() -> void: axis_lock_angular_x = true axis_lock_angular_z = true angular_damp = 6.0 contact_monitor = true max_contacts_reported = 4 func _integrate_forces(state): # Input as 2D vector var input2v := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") # Camera based movement var forward := Vector3.FORWARD * -1.0 var right := Vector3.RIGHT if cam: forward = cam.global_transform.basis.z right = cam.global_transform.basis.x # project onto ground plane so looking up/down doesn't tilt movement forward.y = 0.0 right.y = 0.0 if forward.length() > 0.0001: forward = forward.normalized() if right.length() > 0.0001: right = right.normalized() var dir := (right * input2v.x + forward * input2v.y).normalized() var target_v := dir * MOVE_SPEED var ax := ACCELLERATION if dir != Vector3.ZERO else DECELLERATION linear_velocity.x = move_toward(linear_velocity.x, target_v.x, ax * state.step) linear_velocity.z = move_toward(linear_velocity.z, target_v.z, ax * state.step) # Jump Logic var on_floor = false for i in state.get_contact_count(): var normal = state.get_contact_local_normal(i) if normal.y > 0.5: on_floor = true break if on_floor and Input.is_action_just_pressed("ui_accept"): linear_velocity.y = JUMP_SPEED