Godot Version
Godot 4.2.2
Question
I’m trying to make a puzzle game that involves moving boxes and precise and trustworthy interaction between them. (I want them to act the same each time the interaction happens)
My problem is that after restarting the level, for some reason the physics change (even if I reposition everything on the exact spot they spawned the first time)
This happens randomly and with seemingly no reason at all, sometimes the blocks get into the place they need fast, and sometimes they take ages.
This is what’s happening, look at the crate on the right the first run and the second run (hovering only makes the sprite bigger)
In case it could help understand the situation, I’ll link both the scene explanation and the full code of the crate.
block_spawner
never moves, and it’s a node that I just use to move the box back to its position each time the game startsSprite2D
and CollisionShape2D
do exactly what their name says.I use
fallTimer
and hitSfx
to make a sound when the block has been falling for too long.Material menu
is a button that I just use to send a signal on hover to make the sprite bigger.hoverSfx
is a sound that plays on hover, and timeOnGround
is used to decide when to start rotating the block to free it from being stuck, however I don’t think it works like it’s supposed to (duration is 0.5s)
extends RigidBody2D
var mat:int = 0
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var falling:bool = false
var tempRotation:float
var savedArea
var notMoving:bool = false
var readyForGame:bool = false
var baseGravity = gravity
var tween:Tween
func _ready() -> void:
lock_rotation = false
freeze = true
resetBlock()
check_material()
func _physics_process(delta) -> void:
if readyForGame != get_parent().get_parent().get_parent().running:
readyForGame = !readyForGame
if readyForGame: freeze = false
else: freeze = true
resetBlock()
if get_parent().get_parent().get_parent().running:
if notMoving:
var roundRotation:float = fmod(rotation_degrees, 90.0)
tempRotation = round(rotation_degrees/90)*90
if linear_velocity.x + linear_velocity.y < 1 and (rotation_degrees > tempRotation+0.1 or rotation_degrees < tempRotation-0.1) and\
$"../timeOnGround".time_left < 0.05 and notMoving:
rotation_degrees = lerp(rotation_degrees, tempRotation, 0.3)
if linear_velocity.x > 270: linear_velocity.x = 270
if linear_velocity.y > 270: linear_velocity.y = 270
if linear_velocity.x > 40 or linear_velocity.y > 40:
if $fallTime.is_stopped() and !falling:
$fallTime.start() #Starts a timer that controls fall time
if $fallTime.time_left <= 0.05 and savedArea == null:
falling = true
notMoving = linear_velocity.x < 2 and linear_velocity.y < 2
if notMoving and $"../timeOnGround".is_stopped(): $"../timeOnGround".start()
else: $"../timeOnGround".stop()
func check_material() -> void:
if mat == 0:
add_to_group("pushable")
modulate.hex(101010)
func _on_area_2d_area_entered(area):
if area.is_in_group("ground") and falling:
savedArea = area
falling = false
$hitSfx.play()
if area.is_in_group("jumpPad"):
linear_velocity.y = -400
if area.is_in_group("superJumpPad"):
linear_velocity.y = -600
func _on_area_2d_area_exited(area) -> void:
if savedArea == area: savedArea = null
func resetBlock() -> void:
global_position = $"..".global_position
linear_velocity.y = 0; linear_velocity.x = 0
rotation_degrees = 0
func _on_material_menu_mouse_entered() -> void:
if !readyForGame:
$"../hoverSfx".play()
resetTween()
tween.tween_property($Sprite2D, "scale", Vector2(1.2,1.2), 0.05).set_ease(Tween.EASE_IN_OUT)
func _on_material_menu_mouse_exited() -> void:
if !readyForGame:
resetTween()
tween.tween_property($Sprite2D, "scale", Vector2(1.0,1.0), 0.05).set_ease(Tween.EASE_IN_OUT)
func resetTween() -> void:
if tween:
tween.kill() # Abort the previous animation.
tween = create_tween()
I have no idea in why this happens, any help is appreciated.
TLDR: blocks get unstuck fast the first time i play a level, get unstuck slow the second time i play and it goes randomly after that
Thanks in advance