Godot Version
4.3
Question
`I’ve got a player with an in-code state machine that’s worked across every scene I’ve plugged it into, which have all been test scenes, so reasonably small.
On boxing out a larger level scene, I’ve run into an issue where the player controller works fine up until they run far enough for their global_position.x to hit 60,000, give or take a few, at which point the state machine breaks down and the character can no longer stay in its Wallgrabbing state. This gif shows the player crossing the threshold–every surface to the left allows the player to wallgrab normally, and every surface to the right flicks back and forth between falling and wallgrabbing states about once per frame. This holds true even if the player runs all the way back to the start of the level, so it doesn’t seem like a time or memory issue but my knowledge there is very limited.
I’ve tested the issue at different Y heights, and though it changes the exact breakpoint very slightly, it always lands between 59,000 and 61,000 on the X-axis with the same behavior change.
Is there some soft cap to sizing on scenes in Godot?
I’m pasting the character’s state machine below, which is all handled within a single code. Apologies for the length. The relevant portion is in the first few sections, but including the rest since there are a few other areas that interact with the Wallgrabbing state.
Any ideas are much appreciated. Thanks!
func _physics_process(delta):
knockback = lerp(knockback, Vector2.DOWN, 0.5)
if state == States.CROUCHING or state == States.CRAWLING:
is_hidden = true
else: is_hidden = false
# Set Gravity
velocity.y += find_gravity() * delta + (knockback.y)
if lifestate == LifeStates.ALIVE:
if raycast_bottom_left.is_colliding() and raycast_top_left.is_colliding():
on_wall_left = true
else: on_wall_left = false
if raycast_bottom_right.is_colliding() and raycast_top_right.is_colliding():
on_wall_right = true
else: on_wall_right = false
#State machine decision tree (no sprite management)
if is_on_floor():
if get_input_velocity() == 0:
if Input.is_action_pressed("input_down") or (crouch_check_left.is_colliding() or crouch_check_right.is_colliding()):
state = States.CROUCHING
else:
state = States.IDLE
if (get_input_velocity() == 1) or (get_input_velocity() == -1):
if Input.is_action_pressed("input_down") or (crouch_check_left.is_colliding() or crouch_check_right.is_colliding()):
state = States.CRAWLING
else:
state = States.RUNNING
if is_on_wall_only() and (can_wall_grab == true):
if on_wall_left == true and (get_input_velocity() == -1):
state = States.WALLGRABBING
is_wall_grabbing_left = true
#gun.wallgrab_left = true
elif on_wall_right == true and (get_input_velocity() == 1):
state = States.WALLGRABBING
is_wall_grabbing_right = true
#gun.wallgrab_right = true
elif (!is_on_floor() and velocity.y < 0) and state != States.WALLJUMPING:
state = States.JUMPING
elif !is_on_floor() and velocity.y > 0.0 and state != States.WALLJUMPING:
state = States.FALLING
#Horizontal Control
if state in [States.IDLE, States.CROUCHING, States.RUNNING, States.CRAWLING, States.JUMPING, States.FALLING]:
if has_control == true:
if get_input_velocity() == 1:
if state == States.CROUCHING or state == States.CRAWLING:
velocity.x = min(velocity.x + acceleration, crawl_speed) + knockback.x
else:
velocity.x = min(velocity.x + acceleration, speed) + knockback.x
elif get_input_velocity() == -1:
if state == States.CROUCHING or state == States.CRAWLING:
velocity.x = max(velocity.x - acceleration, -crawl_speed) + knockback.x
else:
velocity.x = max(velocity.x - acceleration, -speed) + knockback.x
else:
velocity.x = lerp(velocity.x, 0.0, deceleration) + knockback.x
can_wall_grab = false
#Edge Sticking
if state == States.IDLE and get_input_velocity() == 0:
if floorcheck_left.is_colliding():
if !floorcheck_right.is_colliding():
velocity.x = -300
else: pass
elif floorcheck_right.is_colliding():
if !floorcheck_left.is_colliding():
velocity.x = 300
else: pass
else: pass
#Single Jump Mechanics
if state in [States.IDLE, States.CROUCHING, States.RUNNING, States.CRAWLING]:
has_double_jumped = false
can_jump = true
if Input.is_action_just_pressed("input_jump"):
jump()
#Double Jump Mechanics
if state in [States.JUMPING, States.FALLING]:
if Input.is_action_just_pressed("input_jump") and has_double_jumped == false:
doublejump()
#Wallgrabbing Mechanics
if state == States.WALLGRABBING:
velocity.y = 0
#var walljump_direction = (mouse_position - position).normalized()
if Input.is_action_just_released("input_left") or Input.is_action_just_released("input_right"):
state = States.FALLING
is_wall_grabbing_left = false
gun.wallgrab_left = false
is_wall_grabbing_right = false
gun.wallgrab_right = false
has_double_jumped = false
if Input.is_action_just_pressed("input_jump"):
state = States.WALLJUMPING
walljump()
#Crouching Mechanics
if state in [States.CROUCHING, States.CRAWLING]:
on_crouch()
else:
on_stand()
#Particle Controller
if state == States.FALLING:
land_particle_emitted = false
jump_particle_emitted = false
if state == States.WALLGRABBING:
jump_particle_emitted = false
if state == States.RUNNING:
run_particles.emitting = true
else:
run_particles.emitting = false
if (state == States.JUMPING or States.FALLING) and is_on_floor():
if land_particle_emitted == false:
land_particles_left.emitting = true
land_particles_right.emitting = true
land_particle_emitted = true
else:
pass
#Sprite Controller
if state == States.IDLE:
body_sprite.play("idle")
if state == States.RUNNING:
body_sprite.play("run")
if state == States.CROUCHING:
body_sprite.play("crouch")
if state == States.CRAWLING:
body_sprite.play("crawl")
if state == States.JUMPING:
body_sprite.play("jump")
if state == States.FALLING:
body_sprite.play("fall")
if state == States.WALLGRABBING:
body_sprite.play("wallgrab")
#flip body sprite for x velocity
if velocity.x < 0:
body_sprite.flip_h = true
if velocity.x > 0:
body_sprite.flip_h = false
#flip head sprite for x velocity
var mouse_position = get_global_mouse_position()
if mouse_position.x < global_position.x:
head_sprite.flip_h = true
else:
head_sprite.flip_h = false
#tilt and squash
if velocity.x < 300 and velocity.x > -300:
sprite_controller.rotation_degrees = 0
if state in [States.CRAWLING, States.CROUCHING, States.WALLGRABBING, States.IDLE]:
sprite_controller.rotation_degrees = 0
else:
if velocity.x < 0:
sprite_controller.rotation_degrees = max((-velocity.x / -speed) * 100, -10)
if velocity.x > 0:
sprite_controller.rotation_degrees = min((velocity.x / speed) * 100, 10)
head_sprite.rotation_degrees = head_tilt_modifier
if state == States.WALLGRABBING:
animation_player.play("RESET")
if is_wall_grabbing_left == true:
head_tilt_modifier = 30
gun.wallgrab_left = true
elif is_wall_grabbing_right:
head_tilt_modifier = -30
gun.wallgrab_right = true
if state != States.WALLGRABBING:
head_tilt_modifier = 0
if animation_player.is_playing() != true:
animation_player.play("default")
else:
pass
if state == States.RUNNING:
animation_player.speed_scale = 5
else:
animation_player.speed_scale = 2
if state in [States.IDLE, States.CROUCHING, States.RUNNING, States.CRAWLING, States.WALLGRABBING]:
sprite_controller.scale.y = 1
sprite_controller.scale.x = 1
else:
if velocity.y == 0:
sprite_controller.scale.x = 1
if velocity.y > 0:
sprite_controller.scale.x = 1 - (velocity.y / fall_gravity)
sprite_controller.scale.y = .8 + (velocity.y / fall_gravity)
if velocity.y < 0:
sprite_controller.scale.x = 1 - (velocity.y / -fall_gravity)
sprite_controller.scale.y = .8 + (velocity.y / -fall_gravity)
#hide gun while crawling and crouching
if state in [States.CROUCHING, States.CRAWLING]:
head_sprite.visible = false
gun.visible = false
gun.gun_available = false
else:
head_sprite.visible = true
gun.gun_available = true
if state != States.WALLGRABBING:
gun.wallgrab_left = false
gun.wallgrab_right = false
look_rotation = gun.gun_rotation
if gun.wallgrab_left == true:
head_sprite.flip_h = false
if gun.wallgrab_right ==true:
head_sprite.flip_h = true
#head sprite rotation
if ((look_rotation > -15 + head_tilt_modifier) and (look_rotation < 15 + head_tilt_modifier)) or ((look_rotation > 165 + head_tilt_modifier) or (look_rotation < -165 + head_tilt_modifier)):
head_sprite.play("straight")
if ((look_rotation > 15 + head_tilt_modifier) and (look_rotation < 45 + head_tilt_modifier)) or ((look_rotation > 135 + head_tilt_modifier) and (look_rotation < 165 + head_tilt_modifier)):
head_sprite.play("down1")
if ((look_rotation > 45 + head_tilt_modifier) and (look_rotation < 135 + head_tilt_modifier)):
head_sprite.play("down2")
if ((look_rotation > -45 + head_tilt_modifier) and (look_rotation < -15 + head_tilt_modifier)) or ((look_rotation > -165 + head_tilt_modifier) and (look_rotation < -135 + head_tilt_modifier)):
head_sprite.play("up1")
if ((look_rotation > -135 + head_tilt_modifier) and (look_rotation < -45 + head_tilt_modifier)):
head_sprite.play("up2")
#gun sprite flip on rotation
if look_rotation > -90 and look_rotation < 90:
gun.gun_sprite.flip_v = false
elif look_rotation > 90 or look_rotation < -90:
gun.gun_sprite.flip_v = true
elif lifestate == LifeStates.DEAD:
state = States.IDLE
deceleration = 0.05
velocity.x = lerp(velocity.x, 0.0, deceleration)
sprite_controller.scale.x = 1
sprite_controller.scale.y = 1
head_sprite.visible = false
gun.visible = false
gun.gun_available = false
body_sprite.play("dead")
sprite_controller.rotation_degrees = 0
`