Unity重写OnServerAddPlayer未生效,玩家颜色场景切换后无法保留
It sounds like your color changes aren't sticking because you're not properly storing the player's color state server-side and initializing it when the player re-spawns during scene switches. Here's a step-by-step solution to get this working:
1. Use a Network-Synced Variable for Player Color
First, ensure your player's color is stored in a [SyncVar] so changes automatically propagate to all clients. Add this to your player's NetworkBehaviour script:
using UnityEngine; using UnityEngine.Networking; public class PlayerColorHandler : NetworkBehaviour { // SyncVar with a hook to update visuals when color changes [SyncVar(hook = nameof(OnColorUpdated))] private Color _currentColor = Color.white; // Call this when the player touches a paint splatter (client-side only) public void ApplyPaintColor(Color newColor) { if (!isLocalPlayer) return; // Only local player can request color changes CmdUpdatePlayerColor(newColor); } // Command to send color change request to server [Command] private void CmdUpdatePlayerColor(Color newColor) { _currentColor = newColor; // Save this color to server-side storage tied to the player's connection var networkManager = FindObjectOfType<CustomNetworkManager>(); networkManager.SavePlayerColor(connectionToClient, newColor); } // Hook that updates the player's visuals when the SyncVar changes private void OnColorUpdated(Color oldColor, Color newColor) { Renderer playerRenderer = GetComponent<Renderer>(); if (playerRenderer != null) { playerRenderer.material.color = newColor; } } }
2. Store Player Color Data Server-Side
In your custom NetworkManager, add a dictionary to track each player's color using their connection ID as the key. This ensures the color persists even when scenes change:
using UnityEngine; using UnityEngine.Networking; using System.Collections.Generic; public class CustomNetworkManager : NetworkManager { private Dictionary<int, Color> _playerColorStorage = new Dictionary<int, Color>(); // Call this from the player's command to save color public void SavePlayerColor(NetworkConnection conn, Color color) { if (_playerColorStorage.ContainsKey(conn.connectionId)) { _playerColorStorage[conn.connectionId] = color; } else { _playerColorStorage.Add(conn.connectionId, color); } } // Clean up data when a player disconnects public override void OnServerDisconnect(NetworkConnection conn) { base.OnServerDisconnect(conn); if (_playerColorStorage.ContainsKey(conn.connectionId)) { _playerColorStorage.Remove(conn.connectionId); } } }
3. Initialize Player Color in OnServerAddPlayer
Now, override OnServerAddPlayer to retrieve the saved color and apply it to the newly spawned player before adding them to the network:
public override void OnServerAddPlayer(NetworkConnection conn) { // Spawn your player prefab GameObject playerInstance = Instantiate(playerPrefab); // Get the saved color for this connection (default to white if no data exists) Color savedColor = Color.white; if (_playerColorStorage.ContainsKey(conn.connectionId)) { savedColor = _playerColorStorage[conn.connectionId]; } // Assign the saved color to the player's SyncVar PlayerColorHandler colorHandler = playerInstance.GetComponent<PlayerColorHandler>(); if (colorHandler != null) { colorHandler._currentColor = savedColor; // The SyncVar hook will automatically update the visuals } // Add the player to the network connection NetworkServer.AddPlayerForConnection(conn, playerInstance); }
Troubleshooting Tips
- Confirm SyncVar is working: Add debug logs in
OnColorUpdatedandCmdUpdatePlayerColorto verify color changes are being sent to the server and synced back to clients. - Check NetworkManager persistence: Ensure your
CustomNetworkManageris marked withDontDestroyOnLoadso it (and the color storage dictionary) survives scene switches. - Verify player prefab setup: Make sure your player prefab has a
NetworkIdentitycomponent, and that thePlayerColorHandlerscript is attached to it.
内容的提问来源于stack exchange,提问作者BenjaFriend

