Portal.cs 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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 TMP 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);
  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. No custom handling for this.
  53. conn.Send(new SceneMessage { sceneName = gameObject.scene.path, sceneOperation = SceneOperation.UnloadAdditive, customHandling = true });
  54. yield return new WaitForSeconds(AdditiveLevelsNetworkManager.singleton.fadeInOut.GetDuration());
  55. NetworkServer.RemovePlayerForConnection(conn, false);
  56. // reposition player on server and client
  57. player.transform.position = startPosition;
  58. player.transform.LookAt(Vector3.up);
  59. // Move player to new subscene.
  60. SceneManager.MoveGameObjectToScene(player, SceneManager.GetSceneByPath(destinationScene));
  61. // Tell client to load the new subscene with custom handling (see NetworkManager::OnClientChangeScene).
  62. conn.Send(new SceneMessage { sceneName = destinationScene, sceneOperation = SceneOperation.LoadAdditive, customHandling = true });
  63. NetworkServer.AddPlayerForConnection(conn, player);
  64. // host client would have been disabled by OnTriggerEnter above
  65. if (NetworkClient.localPlayer != null && NetworkClient.localPlayer.TryGetComponent(out PlayerController playerController))
  66. playerController.enabled = true;
  67. }
  68. }
  69. }
  70. }