slowpoker/Assets/Mirror/Examples/CharacterSelection/Scripts/NetworkManagerCharacterSelection.cs
2024-10-17 17:23:05 +03:00

135 lines
5.9 KiB
C#

using UnityEngine;
namespace Mirror.Examples.CharacterSelection
{
public class NetworkManagerCharacterSelection : NetworkManager
{
// See the scene 'SceneMapSpawnWithNoCharacter', to spawn as empty player.
// 'SceneMap' will auto spawn as random player character.
// Compare Network Manager inspector setups to see the difference between the two.
// Either of these allow selecting character after spawning in too.
public bool SpawnAsCharacter = true;
public static new NetworkManagerCharacterSelection singleton => (NetworkManagerCharacterSelection)NetworkManager.singleton;
private CharacterData characterData;
public override void Awake()
{
characterData = CharacterData.characterDataSingleton;
if (characterData == null)
{
Debug.Log("Add CharacterData prefab singleton into the scene.");
return;
}
base.Awake();
}
public struct CreateCharacterMessage : NetworkMessage
{
public string playerName;
public int characterNumber;
public Color characterColour;
}
public struct ReplaceCharacterMessage : NetworkMessage
{
public CreateCharacterMessage createCharacterMessage;
}
public override void OnStartServer()
{
base.OnStartServer();
NetworkServer.RegisterHandler<CreateCharacterMessage>(OnCreateCharacter);
NetworkServer.RegisterHandler<ReplaceCharacterMessage>(OnReplaceCharacterMessage);
}
public override void OnClientConnect()
{
base.OnClientConnect();
if (SpawnAsCharacter)
{
// you can send the message here, or wherever else you want
CreateCharacterMessage characterMessage = new CreateCharacterMessage
{
playerName = StaticVariables.playerName,
characterNumber = StaticVariables.characterNumber,
characterColour = StaticVariables.characterColour
};
NetworkClient.Send(characterMessage);
}
}
void OnCreateCharacter(NetworkConnectionToClient conn, CreateCharacterMessage message)
{
Transform startPos = GetStartPosition();
// check if the save data has been pre-set
if (message.playerName == "")
{
Debug.Log("OnCreateCharacter name invalid or not set, use random.");
message.playerName = "Player: " + UnityEngine.Random.Range(100, 1000);
}
// check that prefab is set, or exists for saved character number data
// could be a cheater, or coding error, or different version conflict
if (message.characterNumber <= 0 || message.characterNumber >= characterData.characterPrefabs.Length)
{
Debug.Log("OnCreateCharacter prefab Invalid or not set, use random.");
message.characterNumber = UnityEngine.Random.Range(1, characterData.characterPrefabs.Length);
}
// check if the save data has been pre-set
if (message.characterColour == new Color(0, 0, 0, 0))
{
Debug.Log("OnCreateCharacter colour invalid or not set, use random.");
message.characterColour = Random.ColorHSV(0f, 1f, 1f, 1f, 0f, 1f);
}
GameObject playerObject = startPos != null
? Instantiate(characterData.characterPrefabs[message.characterNumber], startPos.position, startPos.rotation)
: Instantiate(characterData.characterPrefabs[message.characterNumber]);
// Apply data from the message however appropriate for your game
// Typically Player would be a component you write with syncvars or properties
CharacterSelection characterSelection = playerObject.GetComponent<CharacterSelection>();
characterSelection.playerName = message.playerName;
characterSelection.characterNumber = message.characterNumber;
characterSelection.characterColour = message.characterColour;
// call this to use this gameobject as the primary controller
NetworkServer.AddPlayerForConnection(conn, playerObject);
}
void OnReplaceCharacterMessage(NetworkConnectionToClient conn, ReplaceCharacterMessage message)
{
// Cache a reference to the current player object
GameObject oldPlayer = conn.identity.gameObject;
GameObject playerObject = Instantiate(characterData.characterPrefabs[message.createCharacterMessage.characterNumber], oldPlayer.transform.position, oldPlayer.transform.rotation);
// Instantiate the new player object and broadcast to clients
// Include true for keepAuthority paramater to prevent ownership change
NetworkServer.ReplacePlayerForConnection(conn, playerObject, true);
// Apply data from the message however appropriate for your game
// Typically Player would be a component you write with syncvars or properties
CharacterSelection characterSelection = playerObject.GetComponent<CharacterSelection>();
characterSelection.playerName = message.createCharacterMessage.playerName;
characterSelection.characterNumber = message.createCharacterMessage.characterNumber;
characterSelection.characterColour = message.createCharacterMessage.characterColour;
// Remove the previous player object that's now been replaced
// Delay is required to allow replacement to complete.
Destroy(oldPlayer, 0.1f);
}
public void ReplaceCharacter(ReplaceCharacterMessage message)
{
NetworkClient.Send(message);
}
}
}