Freeze players during map load: kill gravity and hide own mesh

- PlayerCharacterController: GravityEnabled toggle. When off, hold
  vertical velocity at zero and skip steep-slope sliding so a frozen
  avatar neither falls nor drifts; true is byte-for-byte the old path.
- GameModeManager: during Loading, additionally disable gravity and
  hide the local body (SkinnedMesh + fur shell), re-asserted each frame
  to catch the mid-load lobby->match respawn. Restored (body shown,
  gravity on) before ActiveMode.Enter() on release to Hide.
- MatchManager: enter Loading *before* SwapScenes so still-bound lobby
  avatars are frozen before their floor unloads. Fixes the player
  falling into the void during the lobby->map scene swap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 4.8 committed 2026-07-06 07:55:40 +02:00
1 parent fba4780c0e
commit a2c8a2c75d
3 files changed
+74 -9

No files matched your search

@@ -151,6 +151,14 @@ public class PlayerCharacterController : MonoBehaviour
/// </summary>
public bool ControlEnabled { get; set; } = true;
/// <summary>
/// When false, gravity, ground-stick and slope-sliding are suspended and the vertical velocity is
/// held at rest, so the avatar hovers at its spawn position instead of settling. Set by the
/// GameModeManager during the pre-Hide loading barrier (alongside <see cref="ControlEnabled"/>) and
/// restored when the Hide phase begins.
/// </summary>
public bool GravityEnabled { get; set; } = true;
/// <summary>
/// When set, the body faces this world-space yaw (degrees) every frame instead of turning toward its
/// movement direction. First-person sets it so the character always faces where the camera looks;
@@ -418,20 +426,30 @@ public class PlayerCharacterController : MonoBehaviour
// (also covers balancing on a sharp box edge).
float slopeAngle = Vector3.Angle(_groundNormal, Vector3.up);
bool onSteepSlope = slideDownSteepSlopes
&& GravityEnabled
&& _controller.isGrounded
&& slopeAngle > _controller.slopeLimit + 0.01f;
if (_controller.isGrounded)
if (!GravityEnabled)
{
if (_verticalVelocity < 0f)
_verticalVelocity = groundedStickVelocity;
// No jumping off a slope too steep to stand on.
if (jumpPressed && !onSteepSlope)
_verticalVelocity = Mathf.Sqrt(jumpHeight * -2f * gravity);
// Loading barrier freeze: no gravity or ground-stick, hold vertical velocity at rest so the
// avatar keeps its spawn position (movement input is already cut via ControlEnabled).
_verticalVelocity = 0f;
}
else
{
if (_controller.isGrounded)
{
if (_verticalVelocity < 0f)
_verticalVelocity = groundedStickVelocity;
_verticalVelocity += gravity * Time.deltaTime;
// No jumping off a slope too steep to stand on.
if (jumpPressed && !onSteepSlope)
_verticalVelocity = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
_verticalVelocity += gravity * Time.deltaTime;
}
Vector3 slideVelocity = Vector3.zero;
if (onSteepSlope)