fix: chat input isolation, mouse lock, multi spawn

- PlayerController: block WASD/jump callbacks when ChatUI is open
- PlayerController: clic droit = unlock souris, clic gauche = re-lock (n'est plus un toggle)
- PlayerController: ajoute ResetInputs() appelé à l'ouverture du chat
- ChatUI: appelle ResetInputs() quand le panel s'ouvre pour éviter les touches collées
- NetworkManager: seed les joueurs déjà présents dans la room à la connexion
  (les OnAdd Colyseus peuvent être manqués si l'état est décodé avant l'enregistrement des callbacks)
- NetworkManager: garde anti-doublon dans OnPlayerAdd
- NetworkManager: fallback sphere si remotePlayerPrefab est null

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-18 08:22:40 +02:00
parent aa27725c4e
commit e2fa2ba8a9
3 changed files with 42 additions and 81 deletions

View File

@@ -180,20 +180,18 @@ public class PlayerController : MonoBehaviour
// Update is called once per frame
void Update()
{
// Toggle cursor lock/unlock avec clic droit (disabled when keybind menu is open)
if (!KeyBindingUI.IsVisible && Mouse.current != null && Mouse.current.rightButton.wasPressedThisFrame)
// Cursor lock: right-click unlocks, left-click re-locks (disabled when any UI panel is open)
if (!ChatUI.IsVisible && !KeyBindingUI.IsVisible && Mouse.current != null)
{
if (Cursor.lockState == CursorLockMode.Locked)
if (Cursor.lockState == CursorLockMode.Locked && Mouse.current.rightButton.wasPressedThisFrame)
{
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
Debug.Log("Cursor UNLOCKED");
}
else
else if (Cursor.lockState != CursorLockMode.Locked && Mouse.current.leftButton.wasPressedThisFrame)
{
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
Debug.Log("Cursor LOCKED");
}
}
@@ -374,33 +372,19 @@ public class PlayerController : MonoBehaviour
public void OnJump(InputAction.CallbackContext context)
{
if (ChatUI.IsVisible) { isJumpPressed = false; jumpPressTime = 0f; return; }
if (context.started)
{
isJumpPressed = true;
jumpPressTime = 0f;
StatsTracker.Instance?.RegisterJump();
Debug.Log("Jump Started");
}
else if (context.performed)
{
// Action validée (utile pour saut immédiat aussi)
Debug.Log("Jump Performed");
}
else if (context.canceled)
{
// Touche relâchée
float jumpForceFactor = Mathf.Clamp01(jumpPressTime / maxJumpHoldTime);
if (IsGrounded())
{
PerformJump(jumpForceFactor * JumpForce);
Debug.Log($"Jump Released after {jumpPressTime}s -> Force factor: {jumpForceFactor}");
}
else
{
Debug.Log("Jump Released but not grounded.");
}
// Reset jump state so gauge goes back to 0
isJumpPressed = false;
jumpPressTime = 0f;
}
@@ -424,75 +408,30 @@ public class PlayerController : MonoBehaviour
public void OnForward(InputAction.CallbackContext context)
{
if (context.started)
{
isForwardHeld = true;
Debug.Log("Forward Action Started");
}
else if (context.performed)
{
// Forward action performed
Debug.Log("Forward Action Performed");
}
else if (context.canceled)
{
isForwardHeld = false;
Debug.Log("Forward Action Canceled");
}
if (ChatUI.IsVisible) { isForwardHeld = false; return; }
if (context.started) isForwardHeld = true;
else if (context.canceled) isForwardHeld = false;
}
public void OnBackwards(InputAction.CallbackContext context)
{
if (context.started)
{
isBackwardsHeld = true;
Debug.Log("Backwards Action Started");
}
else if (context.performed)
{
Debug.Log("Backwards Action Performed");
}
else if (context.canceled)
{
isBackwardsHeld = false;
Debug.Log("Backwards Action Canceled");
}
if (ChatUI.IsVisible) { isBackwardsHeld = false; return; }
if (context.started) isBackwardsHeld = true;
else if (context.canceled) isBackwardsHeld = false;
}
public void OnLeft(InputAction.CallbackContext context)
{
if (context.started)
{
isLeftHeld = true;
Debug.Log("Left Action Started");
}
else if (context.performed)
{
Debug.Log("Left Action Performed");
}
else if (context.canceled)
{
isLeftHeld = false;
Debug.Log("Left Action Canceled");
}
if (ChatUI.IsVisible) { isLeftHeld = false; return; }
if (context.started) isLeftHeld = true;
else if (context.canceled) isLeftHeld = false;
}
public void OnRight(InputAction.CallbackContext context)
{
if (context.started)
{
isRightHeld = true;
Debug.Log("Right Action Started");
}
else if (context.performed)
{
Debug.Log("Right Action Performed");
}
else if (context.canceled)
{
isRightHeld = false;
Debug.Log("Right Action Canceled");
}
if (ChatUI.IsVisible) { isRightHeld = false; return; }
if (context.started) isRightHeld = true;
else if (context.canceled) isRightHeld = false;
}
// --- Bump collision with remote players ---
@@ -564,6 +503,16 @@ public class PlayerController : MonoBehaviour
_isSquashing = false;
}
public void ResetInputs()
{
isForwardHeld = false;
isBackwardsHeld = false;
isLeftHeld = false;
isRightHeld = false;
isJumpPressed = false;
jumpPressTime = 0f;
}
void OnDestroy()
{
// Clean up name label (it's not parented to the ball)

View File

@@ -163,6 +163,13 @@ public class NetworkManager : MonoBehaviour
_room.OnMessage<ChatUI.ChatMessage>("chat", msg => { ChatUI.Instance?.ReceiveChatMessage(msg); });
_room.OnLeave += OnRoomLeave;
// Seed players already present in the room (state decoded before callbacks were registered)
if (_room.State.players != null)
{
foreach (var kvp in _room.State.players)
OnPlayerAdd(kvp.Key, kvp.Value);
}
OnConnected?.Invoke();
}
@@ -257,11 +264,14 @@ public class NetworkManager : MonoBehaviour
PlayerCount = _room.State.players?.Count ?? 0;
if (sessionId == LocalSessionId) return;
if (_remotePlayers.ContainsKey(sessionId)) return; // prevent duplicate spawn
if (remotePlayerPrefab != null)
{
Vector3 spawnPos = new Vector3(player.x, player.y, player.z);
GameObject remoteBall = Instantiate(remotePlayerPrefab, spawnPos, Quaternion.identity);
GameObject remoteBall = remotePlayerPrefab != null
? Instantiate(remotePlayerPrefab, spawnPos, Quaternion.identity)
: GameObject.CreatePrimitive(PrimitiveType.Sphere);
remoteBall.transform.position = spawnPos;
remoteBall.name = $"RemotePlayer_{player.name}_{sessionId[..6]}";
var controller = remoteBall.GetComponent<RemotePlayerController>()

View File

@@ -76,6 +76,8 @@ public class ChatUI : MonoBehaviour
_pollTimer = POLL_INTERVAL; // poll immediately
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
// Release held movement keys so the ball doesn't keep moving while typing
FindFirstObjectByType<PlayerController>()?.ResetInputs();
}
else
{