Fix: rejoining stacked players on top of each other (one fell through)
checkpoint / checkpoint (push) Successful in 1m40s

All players spawned at the exact same PlayerSpawn point and were on the
same collision layer, so two overlapping CharacterBody3Ds triggered a
physics depenetration shove that could launch one through the 1-unit-thick
floor.

- server.gd: golden-angle spawn spread -- each join lands ~1m+ from the
  others, growing outward, never exactly repeating.
- server_player.tscn + player.tscn: players on collision layer 2, mask 1
  (world only) -- players no longer collide with each other at all
  (fine for a social game; also removes the shove).
- player_spawner.gd + player.gd: hard safety net -- if y < -10 (any
  tunnel-through), snap back to the spawn instead of falling forever.

Verified: 3 server players spawn 1.15m+ apart, none fall, all rest on the
floor. 2p multiplayer + network_client smokes green.

Client-side -- rebuild the exe.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015jtxAiu5dAW4WxCNdGkrkJ
This commit is contained in:
2026-09-06 00:00:27 +00:00
parent 80f24bfd01
commit da4e1420ee
5 changed files with 39 additions and 1 deletions
+11
View File
@@ -14,6 +14,10 @@ const GRAVITY := 9.8
var peer_id: int = -1
## Where the server spawned this player (set by server.gd). Used as the
## respawn point if the player somehow ends up below the world.
var spawn_position: Vector3 = Vector3(0, 1.5, 0)
## Highest input seq applied authoritatively so far (echoed in snapshots so
## the client can drop acked inputs and replay the rest).
var last_applied_seq: int = 0
@@ -38,6 +42,13 @@ func _physics_process(delta: float) -> void:
rotation.y = _look_yaw
# Safety net: if a player ends up below the world (physics shove, tunnel
# through the floor), put them back on their spawn instead of falling
# forever.
if global_position.y < -10.0:
global_position = spawn_position
velocity = Vector3.ZERO
func _integrate(move_x: float, move_z: float, jump: bool, delta: float) -> void:
if not is_on_floor():