Portal.cs 4.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. using System.Collections;
  2. using System.IO;
  3. using System.Text.RegularExpressions;
  4. using UnityEngine;
  5. using UnityEngine.SceneManagement;
  6. namespace Mirror.Examples.AdditiveLevels
  7. {
  8. public class Portal : NetworkBehaviour
  9. {
  10. [Scene, Tooltip("Which scene to send player from here")]
  11. public string destinationScene;
  12. [Tooltip("Where to spawn player in Destination Scene")]
  13. public Vector3 startPosition;
  14. [Tooltip("Reference to child TextMesh label")]
  15. public TextMesh label; // don't depend on TMPro. 2019 errors.
  16. [SyncVar(hook = nameof(OnLabelTextChanged))]
  17. public string labelText;
  18. public void OnLabelTextChanged(string _, string newValue)
  19. {
  20. label.text = labelText;
  21. }
  22. public override void OnStartServer()
  23. {
  24. labelText = Path.GetFileNameWithoutExtension(destinationScene).Replace("MirrorAdditiveLevels","");
  25. // Simple Regex to insert spaces before capitals, numbers
  26. labelText = Regex.Replace(labelText, @"\B[A-Z0-9]+", " $0");
  27. }
  28. public override void OnStartClient()
  29. {
  30. if (label.TryGetComponent(out LookAtMainCamera lookAtMainCamera))
  31. lookAtMainCamera.enabled = true;
  32. }
  33. // Note that I have created layers called Player(6) and Portal(7) and set them
  34. // up in the Physics collision matrix so only Player collides with Portal.
  35. void OnTriggerEnter(Collider other)
  36. {
  37. // tag check in case you didn't set up the layers and matrix as noted above
  38. if (!other.CompareTag("Player")) return;
  39. // applies to host client on server and remote clients
  40. if (other.TryGetComponent(out PlayerController playerController))
  41. playerController.enabled = false;
  42. if (isServer)
  43. StartCoroutine(SendPlayerToNewScene(other.gameObject));
  44. }
  45. [ServerCallback]
  46. IEnumerator SendPlayerToNewScene(GameObject player)
  47. {
  48. if (player.TryGetComponent(out NetworkIdentity identity))
  49. {
  50. NetworkConnectionToClient conn = identity.connectionToClient;
  51. if (conn == null) yield break;
  52. // Tell client to unload previous subscene with custom handling (see NetworkManager::OnClientChangeScene).
  53. conn.Send(new SceneMessage { sceneName = gameObject.scene.path, sceneOperation = SceneOperation.UnloadAdditive, customHandling = true });
  54. // wait for fader to complete
  55. yield return new WaitForSeconds(AdditiveLevelsNetworkManager.singleton.fadeInOut.GetDuration());
  56. // Remove player after fader has completed
  57. NetworkServer.RemovePlayerForConnection(conn, false);
  58. // reposition player on server and client
  59. player.transform.position = startPosition;
  60. // Rotate player to face center of scene
  61. // Player is 2m tall with pivot at 0,1,0 so we need to look at
  62. // 1m height to not tilt the player down to look at origin
  63. player.transform.LookAt(Vector3.up);
  64. // Move player to new subscene.
  65. SceneManager.MoveGameObjectToScene(player, SceneManager.GetSceneByPath(destinationScene));
  66. // Tell client to load the new subscene with custom handling (see NetworkManager::OnClientChangeScene).
  67. conn.Send(new SceneMessage { sceneName = destinationScene, sceneOperation = SceneOperation.LoadAdditive, customHandling = true });
  68. // Player will be spawned after destination scene is loaded
  69. NetworkServer.AddPlayerForConnection(conn, player);
  70. // host client playerController would have been disabled by OnTriggerEnter above
  71. // Remote client players are respawned with playerController already enabled
  72. if (NetworkClient.localPlayer != null && NetworkClient.localPlayer.TryGetComponent(out PlayerController playerController))
  73. playerController.enabled = true;
  74. }
  75. }
  76. }
  77. }