Input_dir is not defined idk why tho

Godot Version

godot 4

Question

i am probably missing a small detail but I can’t find out why it’s defined, here’s the code:

extends CharacterBody3D

variables

Speed

var current_speed = 5.0
var lerp_speed = 10.0
var air_lerp_speed = 3.0
var direction = Vector3.ZERO

Crouching

var crouching_depth = -0.5

Sliding

var slide_timer = 0.0
var slide_timer_max = 1.0
var slide_vector = Vector2.ZERO
var slide_speed = 10.0

head bobbing

var head_bobbing_vector = Vector2.ZERO
var head_bobbing_index = 0.0
var head_bobbing_current_intensity = 0.0

Stairs

var _last_frame_was_on_floor = -INF
var _snapped_to_stairs_last_frame := false

State variables

var walking = false
var sprinting = false
var crouching = false
var free_looking = false
var sliding = false

camera dir

var cam_aligned_wish_dir := Vector3.ZERO
var wish_dir := Vector3.ZERO

onready variables

@onready var Neck: Node3D = $Neck
@onready var head: Node3D = $Neck/head
@onready var eyes: Node3D = $Neck/head/Eyes
@onready var camera_3d: Camera3D = $Neck/head/Eyes/Camera3D
@onready var standing_collision: CollisionShape3D = $Standing_Collision
@onready var crouching_collision: CollisionShape3D = $Crouching_Collision
@onready var ray_cast_3d: RayCast3D = $RayCast3D

exported variables

speed

@export var walking_speed = 5.0
@export var sprinting_speed = 8.0
@export var crouching_speed = 3.0
@export var swim_up_speed := 10.0

free looking

@export var mouse_sens = 0.25
@export var free_looking_tilt_amount = 8

head bobbing

@export var head_bobbing_sprinting_speed = 22.0
@export var head_bobbing_walking_speed = 14.0
@export var head_bobbing_crouching_speed = 10.0

head bobbing intensity

@export var head_bobbing_sprinting_intensity = 0.2
@export var head_bobbing_walking_intensity = 0.1
@export var head_bobbing_crouching_intensity = 0.05

constants

const jump_velocity = 4.5
const MAX_STEP_HEIGHT = 0.5

#--------------------------------------------------------------------------------------------------------------------------------------------

This runs at the beginning of the game

func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

#----------------------------------------------------------------------------------------------------------------------------------

var _saved_camera_global_pos = null
func _save_camera_pos_for_smoothing():
if _saved_camera_global_pos == null:
_saved_camera_global_pos = %Eyes.global_position

func _slide_camera_smooth_back_to_origin(delta):
if _saved_camera_global_pos == null: return
%Eyes.global_position.y = _saved_camera_global_pos.y
%Eyes.position.y = clamp(%Eyes.position.y, -0.7, 0.7) # Clamp incase teleported
var move_amount = max(self.velocity.length() * delta, current_speed/2 * delta)
%Eyes.position.y = move_toward(%Eyes.position.y, 0.0, move_amount)
_saved_camera_global_pos = %Eyes.global_position
if %Eyes.position.y == 0:
_saved_camera_global_pos = null

func _snap_down_to_stairs_check() → void:
var did_snap := false
var floor_below : bool = %“Stairs Below”.is_colliding() and not is_surface_too_steep(%“Stairs Below”.get_collision_normal())
var was_on_floor_last_frame = Engine.get_physics_frames() == _last_frame_was_on_floor
if not is_on_floor() and velocity.y <= 0 and (was_on_floor_last_frame or _snapped_to_stairs_last_frame) and floor_below:
var body_test_result = PhysicsTestMotionResult3D.new()
if _run_body_test_motion(self.global_transform, Vector3(0,-MAX_STEP_HEIGHT,0), body_test_result):
_save_camera_pos_for_smoothing()
var translate_y = body_test_result.get_travel().y
self.position.y += translate_y
apply_floor_snap()
did_snap = true
_snapped_to_stairs_last_frame = did_snap

func _snap_up_stairs_check(delta) → bool:
if not is_on_floor() and not _snapped_to_stairs_last_frame: return false
if self.velocity.y > 0 or (self.velocity * Vector3(1,0,1)).length() == 0: return false
var expected_move_motion = self.velocity * Vector3(1,0,1) * delta
var step_pos_with_clearance = self.global_transform.translated(expected_move_motion + Vector3(0, MAX_STEP_HEIGHT * 2, 0))
var down_check_result = PhysicsTestMotionResult3D.new()
if (_run_body_test_motion(step_pos_with_clearance, Vector3(0,-MAX_STEP_HEIGHT*2,0), down_check_result)
and (down_check_result.get_collider().is_class(“StaticBody3D”) or down_check_result.get_collider().is_class(“CSGShape3D”))):
var step_height = ((step_pos_with_clearance.origin + down_check_result.get_travel()) - self.global_position).y
if step_height > MAX_STEP_HEIGHT or step_height <= 0.01 or (down_check_result.get_collision_point() - self.global_position).y > MAX_STEP_HEIGHT: return false
%“Stairs Above”.global_position = down_check_result.get_collision_point() + Vector3(0,MAX_STEP_HEIGHT,0) + expected_move_motion.normalized() * 0.1
%“Stairs Above”.force_raycast_update()
if %“Stairs Above”.is_colliding() and not is_surface_too_steep(%“Stairs Above”.get_collision_normal()):
_save_camera_pos_for_smoothing()
self.global_position = step_pos_with_clearance.origin + down_check_result.get_travel()
apply_floor_snap()
_snapped_to_stairs_last_frame = true
return true
return false

This is if inputs/buttons are pressed

func _input(event):
if Input.is_action_just_pressed(“Quit”):
get_tree().quit()

if event is InputEventMouseMotion:
	if free_looking:
		Neck.rotate_y(deg_to_rad(-event.relative.x * mouse_sens))
		Neck.rotation.y = clamp(Neck.rotation.y, deg_to_rad(-120), deg_to_rad(120))
	else:
		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(-89), deg_to_rad(89))

#------------------------------------------------------------------------------------------------------------------------------

func _physics_process(delta):
var input_dir = Input.get_vector(“Left”, “Right”, “Forward”, “Backward”)

if is_on_floor(): _last_frame_was_on_floor = Engine.get_physics_frames()


current_speed = lerp(current_speed, crouching_speed, delta * lerp_speed)
head.position.y = lerp(head.position.y,crouching_depth, delta * lerp_speed)
	
standing_collision.disabled = true
crouching_collision.disabled = false



if sprinting && input_dir != Vector2.ZERO:
	sliding = true
	slide_timer = slide_timer_max
	slide_vector = input_dir
	free_looking = true
	
	walking = false
	sprinting = false
	crouching = true
	
elif !ray_cast_3d.is_colliding():
	
	standing_collision.disabled = false
	crouching_collision.disabled = true
	
	head.position.y = lerp(head.position.y,0.0, delta * lerp_speed)
	
	if Input.is_action_pressed("Sprint"):
		
		current_speed = lerp(current_speed, sprinting_speed, delta * lerp_speed)
		
		walking = false
		sprinting = true
		crouching = false
		
	else:
		current_speed = lerp(current_speed, walking_speed, delta * lerp_speed)
		
		walking = true
		sprinting = false
		crouching = false

# Free looking
if Input.is_action_pressed("free_look") || sliding:
	free_looking = true
	
	if sliding:
		camera_3d.rotation.z = lerp(camera_3d.rotation.z,-deg_to_rad(7.0), delta * lerp_speed)
	else:
		camera_3d.rotation.z = -deg_to_rad(Neck.rotation.y * free_looking_tilt_amount)
	
else:
	free_looking = false
	Neck.rotation.y = lerp(Neck.rotation.y,0.0, delta * lerp_speed)
	camera_3d.rotation.z = lerp(camera_3d.rotation.z,0.0, delta * lerp_speed)

if sliding:
	slide_timer -= delta
	if slide_timer <= 0:
		sliding = false
		free_looking = false

if sprinting:
	head_bobbing_current_intensity = head_bobbing_sprinting_intensity
	head_bobbing_index += head_bobbing_sprinting_speed * delta
elif walking:
	head_bobbing_current_intensity = head_bobbing_walking_intensity
	head_bobbing_index += head_bobbing_walking_speed * delta
elif crouching:
	head_bobbing_current_intensity = head_bobbing_crouching_intensity
	head_bobbing_index += head_bobbing_crouching_speed * delta

if is_on_floor() && !sliding && input_dir != Vector2.ZERO:
	head_bobbing_vector.y = sin(head_bobbing_index)
	head_bobbing_vector.x = sin(head_bobbing_index / 2) + 0.5
	
	eyes.position.y = lerp(eyes.position.y, head_bobbing_vector.y * (head_bobbing_current_intensity / 2.0), delta * lerp_speed)
	eyes.position.x = lerp(eyes.position.x, head_bobbing_vector.x * head_bobbing_current_intensity, delta * lerp_speed)
else:
	eyes.position.y = lerp(eyes.position.y, 0.0 , delta * lerp_speed)
	eyes.position.x = lerp(eyes.position.x, 0.0 , delta * lerp_speed)


# Add the gravity.
if not is_on_floor():
	velocity += get_gravity() * delta

func _handle_water_physics(delta) → bool:
if get_tree().get_nodes_in_group(“water_area”).all(func(area): return !area.overlaps_body(self)):
return false

if not is_on_floor():
	velocity.y -= ProjectSettings.get_setting("physics/3d/default_gravity") * 0.1 * delta

self.velocity += cam_aligned_wish_dir * current_speed * delta

if Input.is_action_pressed("Jump"):
	self.velocity.y += swim_up_speed * delta

# Dampen velocity when in water
self.velocity = self.velocity.lerp(Vector3.ZERO, 2 * delta)

return true


# Handle jump.
if is_on_floor() or _snapped_to_stairs_last_frame:
	if Input.is_action_just_pressed("Jump") and is_on_floor():
		velocity.y = jump_velocity
		sliding = false



# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.

THIS IS THE PROBLEM

if is_on_floor():
	if direction != Vector2.ZERO:
		direction = lerp(direction,(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),delta * lerp_speed)
	else:
		direction = lerp(direction,(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),delta * air_lerp_speed)

if sliding:
	direction = (transform.basis * Vector3(slide_vector.x, 0, slide_vector.y)).normalized()
	current_speed = (slide_timer + 0.1) * slide_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)

if not _snap_up_stairs_check(delta):
	move_and_slide()
	_snap_down_to_stairs_check()

func is_surface_too_steep(normal : Vector3) → bool:
return normal.angle_to(Vector3.UP) > self.floor_max_angle

func _run_body_test_motion(from : Transform3D, motion : Vector3, result = null) → bool:
if not result: result = PhysicsTestMotionParameters3D.new()
var params = PhysicsTestMotionParameters3D.new()
params.from = from
params.motion = motion
return PhysicsServer3D.body_test_motion(self.get_rid(), params, result)

Seems like input_dir was defined in _physics_process, not _handle_water_physics

Make sure to paste your scripts between three ticks ```

thx ok let me try it

i can’t move now my bad:



# variables
# Speed
var current_speed = 5.0
var lerp_speed = 10.0
var air_lerp_speed = 3.0
var direction = Vector3.ZERO
# Crouching
var crouching_depth = -0.5
# Sliding
var slide_timer = 0.0
var slide_timer_max = 1.0
var slide_vector = Vector2.ZERO
var slide_speed = 10.0
# head bobbing
var head_bobbing_vector = Vector2.ZERO
var head_bobbing_index = 0.0
var head_bobbing_current_intensity = 0.0
# Stairs
var _last_frame_was_on_floor = -INF
var _snapped_to_stairs_last_frame := false
# State variables
var walking = false
var sprinting = false
var crouching = false
var free_looking = false
var sliding = false
# camera dir
var cam_aligned_wish_dir := Vector3.ZERO
var wish_dir := Vector3.ZERO

# onready variables
@onready var Neck: Node3D = $Neck
@onready var head: Node3D = $Neck/head
@onready var eyes: Node3D = $Neck/head/Eyes
@onready var camera_3d: Camera3D = $Neck/head/Eyes/Camera3D
@onready var standing_collision: CollisionShape3D = $Standing_Collision
@onready var crouching_collision: CollisionShape3D = $Crouching_Collision
@onready var ray_cast_3d: RayCast3D = $RayCast3D

# exported variables
# speed
@export var walking_speed = 5.0
@export var sprinting_speed = 8.0
@export var crouching_speed = 3.0
@export var swim_up_speed := 10.0
# free looking
@export var mouse_sens = 0.25
@export var free_looking_tilt_amount = 8
# head bobbing
@export var head_bobbing_sprinting_speed = 22.0
@export var head_bobbing_walking_speed = 14.0
@export var head_bobbing_crouching_speed = 10.0
# head bobbing intensity
@export var head_bobbing_sprinting_intensity = 0.2
@export var head_bobbing_walking_intensity = 0.1
@export var head_bobbing_crouching_intensity = 0.05
# constants
const jump_velocity = 4.5
const MAX_STEP_HEIGHT = 0.5

#--------------------------------------------------------------------------------------------------------------------------------------------

func get_move_speed() -> float:
	if crouching:
		return walking_speed * 0.8
	return sprinting_speed if Input.is_action_pressed("Sprint") else walking_speed

# This runs at the beginning of the game
func _ready():
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

#----------------------------------------------------------------------------------------------------------------------------------

var _saved_camera_global_pos = null
func _save_camera_pos_for_smoothing():
	if _saved_camera_global_pos == null:
		_saved_camera_global_pos = %Eyes.global_position

func _slide_camera_smooth_back_to_origin(delta):
	if _saved_camera_global_pos == null: return
	%Eyes.global_position.y = _saved_camera_global_pos.y
	%Eyes.position.y = clamp(%Eyes.position.y, -0.7, 0.7) # Clamp incase teleported
	var move_amount = max(self.velocity.length() * delta, current_speed/2 * delta)
	%Eyes.position.y = move_toward(%Eyes.position.y, 0.0, move_amount)
	_saved_camera_global_pos = %Eyes.global_position
	if %Eyes.position.y == 0:
		_saved_camera_global_pos = null

func _snap_down_to_stairs_check() -> void:
	var did_snap := false
	var floor_below : bool = %"Stairs Below".is_colliding() and not is_surface_too_steep(%"Stairs Below".get_collision_normal())
	var was_on_floor_last_frame = Engine.get_physics_frames() == _last_frame_was_on_floor
	if not is_on_floor() and velocity.y <= 0 and (was_on_floor_last_frame or _snapped_to_stairs_last_frame) and floor_below:
		var body_test_result = PhysicsTestMotionResult3D.new()
		if _run_body_test_motion(self.global_transform, Vector3(0,-MAX_STEP_HEIGHT,0), body_test_result):
			_save_camera_pos_for_smoothing()
			var translate_y = body_test_result.get_travel().y
			self.position.y += translate_y
			apply_floor_snap()
			did_snap = true
	_snapped_to_stairs_last_frame = did_snap

func _snap_up_stairs_check(delta) -> bool:
	if not is_on_floor() and not _snapped_to_stairs_last_frame: return false
	if self.velocity.y > 0 or (self.velocity * Vector3(1,0,1)).length() == 0: return false
	var expected_move_motion = self.velocity * Vector3(1,0,1) * delta
	var step_pos_with_clearance = self.global_transform.translated(expected_move_motion + Vector3(0, MAX_STEP_HEIGHT * 2, 0))
	var down_check_result = PhysicsTestMotionResult3D.new()
	if (_run_body_test_motion(step_pos_with_clearance, Vector3(0,-MAX_STEP_HEIGHT*2,0), down_check_result)
	and (down_check_result.get_collider().is_class("StaticBody3D") or down_check_result.get_collider().is_class("CSGShape3D"))):
		var step_height = ((step_pos_with_clearance.origin + down_check_result.get_travel()) - self.global_position).y
		if step_height > MAX_STEP_HEIGHT or step_height <= 0.01 or (down_check_result.get_collision_point() - self.global_position).y > MAX_STEP_HEIGHT: return false
		%"Stairs Above".global_position = down_check_result.get_collision_point() + Vector3(0,MAX_STEP_HEIGHT,0) + expected_move_motion.normalized() * 0.1
		%"Stairs Above".force_raycast_update()
		if %"Stairs Above".is_colliding() and not is_surface_too_steep(%"Stairs Above".get_collision_normal()):
			_save_camera_pos_for_smoothing()
			self.global_position = step_pos_with_clearance.origin + down_check_result.get_travel()
			apply_floor_snap()
			_snapped_to_stairs_last_frame = true
			return true
	return false


# This is if inputs/buttons are pressed
func _input(event):
	if Input.is_action_just_pressed("Quit"):
		get_tree().quit()
	
	if event is InputEventMouseMotion:
		if free_looking:
			Neck.rotate_y(deg_to_rad(-event.relative.x * mouse_sens))
			Neck.rotation.y = clamp(Neck.rotation.y, deg_to_rad(-120), deg_to_rad(120))
		else:
			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(-89), deg_to_rad(89))

#------------------------------------------------------------------------------------------------------------------------------

func _physics_process(delta):
	var input_dir = Input.get_vector("Left", "Right", "Forward", "Backward")
	
	if is_on_floor(): _last_frame_was_on_floor = Engine.get_physics_frames()
	
	
	current_speed = lerp(current_speed, crouching_speed, delta * lerp_speed)
	head.position.y = lerp(head.position.y,crouching_depth, delta * lerp_speed)
		
	standing_collision.disabled = true
	crouching_collision.disabled = false
	
	
	
	if sprinting && input_dir != Vector2.ZERO:
		sliding = true
		slide_timer = slide_timer_max
		slide_vector = input_dir
		free_looking = true
		
		walking = false
		sprinting = false
		crouching = true
		
	elif !ray_cast_3d.is_colliding():
		
		standing_collision.disabled = false
		crouching_collision.disabled = true
		
		head.position.y = lerp(head.position.y,0.0, delta * lerp_speed)
		
		if Input.is_action_pressed("Sprint"):
			
			current_speed = lerp(current_speed, sprinting_speed, delta * lerp_speed)
			
			walking = false
			sprinting = true
			crouching = false
			
		else:
			current_speed = lerp(current_speed, walking_speed, delta * lerp_speed)
			
			walking = true
			sprinting = false
			crouching = false
	
	# Free looking
	if Input.is_action_pressed("free_look") || sliding:
		free_looking = true
		
		if sliding:
			camera_3d.rotation.z = lerp(camera_3d.rotation.z,-deg_to_rad(7.0), delta * lerp_speed)
		else:
			camera_3d.rotation.z = -deg_to_rad(Neck.rotation.y * free_looking_tilt_amount)
		
	else:
		free_looking = false
		Neck.rotation.y = lerp(Neck.rotation.y,0.0, delta * lerp_speed)
		camera_3d.rotation.z = lerp(camera_3d.rotation.z,0.0, delta * lerp_speed)
	
	if sliding:
		slide_timer -= delta
		if slide_timer <= 0:
			sliding = false
			free_looking = false
	
	if sprinting:
		head_bobbing_current_intensity = head_bobbing_sprinting_intensity
		head_bobbing_index += head_bobbing_sprinting_speed * delta
	elif walking:
		head_bobbing_current_intensity = head_bobbing_walking_intensity
		head_bobbing_index += head_bobbing_walking_speed * delta
	elif crouching:
		head_bobbing_current_intensity = head_bobbing_crouching_intensity
		head_bobbing_index += head_bobbing_crouching_speed * delta
	
	if is_on_floor() && !sliding && input_dir != Vector2.ZERO:
		head_bobbing_vector.y = sin(head_bobbing_index)
		head_bobbing_vector.x = sin(head_bobbing_index / 2) + 0.5
		
		eyes.position.y = lerp(eyes.position.y, head_bobbing_vector.y * (head_bobbing_current_intensity / 2.0), delta * lerp_speed)
		eyes.position.x = lerp(eyes.position.x, head_bobbing_vector.x * head_bobbing_current_intensity, delta * lerp_speed)
	else:
		eyes.position.y = lerp(eyes.position.y, 0.0 , delta * lerp_speed)
		eyes.position.x = lerp(eyes.position.x, 0.0 , delta * lerp_speed)
	
	
	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta
	
func _handle_water_physics(delta) -> bool:
	if get_tree().get_nodes_in_group("water_area").all(func(area): return !area.overlaps_body(self)):
		return false
	
	if not is_on_floor():
		velocity.y -= ProjectSettings.get_setting("physics/3d/default_gravity") * 0.1 * delta
	var input_dir = Input.get_vector("Left", "Right", "Forward", "Backward")
	wish_dir = self.global_transform.basis * Vector3(input_dir.x, 0., input_dir.y)
	cam_aligned_wish_dir = $Neck/head/Eyes/Camera3D.global_transform.basis * Vector3(input_dir.x, 0., input_dir.y)
	self.velocity += cam_aligned_wish_dir * get_move_speed() * delta
	
	if Input.is_action_pressed("Jump"):
		self.velocity.y += swim_up_speed * delta
	
	# Dampen velocity when in water
	self.velocity = self.velocity.lerp(Vector3.ZERO, 2 * delta)
	
	return true
	
	
	# Handle jump.
	if not _handle_water_physics(delta):
		if is_on_floor() or _snapped_to_stairs_last_frame:
			if Input.is_action_just_pressed("Jump") and is_on_floor():
				velocity.y = jump_velocity
				sliding = false
	
	
	
	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.

	if is_on_floor():
		if direction != Vector2.ZERO:
			direction = lerp(direction,(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),delta * lerp_speed)
		else:
			direction = lerp(direction,(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),delta * air_lerp_speed)

	if sliding:
		direction = (transform.basis * Vector3(slide_vector.x, 0, slide_vector.y)).normalized()
		current_speed = (slide_timer + 0.1) * slide_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)
	
	if not _snap_up_stairs_check(delta):
		move_and_slide()
		_snap_down_to_stairs_check()

func is_surface_too_steep(normal : Vector3) -> bool:
	return normal.angle_to(Vector3.UP) > self.floor_max_angle

func _run_body_test_motion(from : Transform3D, motion : Vector3, result = null) -> bool:
	if not result: result = PhysicsTestMotionParameters3D.new()
	var params = PhysicsTestMotionParameters3D.new()
	params.from = from
	params.motion = motion
	return PhysicsServer3D.body_test_motion(self.get_rid(), params, result)

What did the script look like when you could move?

it has something to do with:

		if direction != Vector2.ZERO:
			direction = lerp(direction,(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),delta * lerp_speed)
		else:
			direction = lerp(direction,(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized(),delta * air_lerp_speed)~~~ OR ~~~ var input_dir = Input.get_vector("Left", "Right", "Forward", "Backward") ~~~ Is it where I'm putting it in the script, I just implemented the water physics maybe that's breaking it the slide, headbob, and etc work