using System.Collections; using FishNet; using FishNet.Connection; using FishNet.Managing.Scened; using FishNet.Object; using UnityEngine; using UnityEngine.EventSystems; public class SceneLoader : NetworkBehaviour, IPointerClickHandler { [SerializeField] private string sceneName; [SerializeField] public bool SceneStack; [SerializeField] private Vector3 spawnPosition; private int _stackedSceneHandle; private void Start() { InstanceFinder.SceneManager.OnLoadEnd += SceneManager_OnLoadEnd; } private void OnDestroy() { if (InstanceFinder.SceneManager != null) InstanceFinder.SceneManager.OnLoadEnd -= SceneManager_OnLoadEnd; } private void OnTriggerEnter(Collider other) { var nob = other.GetComponent(); if (nob != null && nob.IsOwner) LoadScene(nob); } public void OnPointerClick(PointerEventData eventData) { Debug.Log("Clicked scene loader"); var nob = eventData.pointerCurrentRaycast.gameObject.GetComponent(); if (nob != null) LoadScene(nob); } private void SceneManager_OnLoadEnd(SceneLoadEndEventArgs data) { if (!data.QueueData.AsServer) return; if (!SceneStack) return; if (_stackedSceneHandle != 0) return; if (data.LoadedScenes.Length > 0) _stackedSceneHandle = data.LoadedScenes[0].handle; } private void LoadScene(NetworkObject nob) { Debug.Log("Loading scene"); var sceneLoadData = new SceneLoadData(SceneLookupData.CreateData(sceneName)); sceneLoadData.ReplaceScenes = ReplaceOption.None; sceneLoadData.Options.AllowStacking = true; var connection = nob.Owner; InstanceFinder.SceneManager.LoadConnectionScenes(nob.Owner, sceneLoadData); MovePlayerToSpawnPositionServerRpc(connection); // move player to spawn position } [ServerRpc(RequireOwnership = false)] private void MovePlayerToSpawnPositionServerRpc(NetworkConnection connection) { Debug.Log("Moving player to spawn position (SERVERRPC)"); StartCoroutine(MovePlayerToSpawnPosition(connection)); } private IEnumerator MovePlayerToSpawnPosition(NetworkConnection connection) { // yield return new WaitForEndOfFrame(); yield return new WaitForSeconds(0.5f); // get players network object var player = connection.FirstObject; if (player != null) { Debug.Log("Moving player to spawn position"); player.transform.position = spawnPosition; UpdatePlayerPositionObserversRpc(player.ObjectId, spawnPosition); } } // Get all scenes loaded for this connection [ServerRpc(RequireOwnership = false)] private void UnloadPreviousSceneServerRpc(NetworkConnection connection, string newSceneName) { var sceneConnections = InstanceFinder.SceneManager.SceneConnections; foreach (var kvp in sceneConnections) { var scene = kvp.Key; var connections = kvp.Value; // Check if this scene is loaded for the current connection if (connections.Contains(connection)) // Unload all scenes except the new one and any persistent scenes /*if (scene.name != newSceneName && !scene.name.Equals("PersistentScene")) { var unloadSceneData = new SceneUnloadData(scene.name); InstanceFinder.SceneManager.UnloadConnectionScenes(connection, unloadSceneData); }*/ // unload scenes where no players are connected if (scene.name != newSceneName) { var unloadSceneData = new SceneUnloadData(scene.name); InstanceFinder.SceneManager.UnloadConnectionScenes(connection, unloadSceneData); } } } [ObserversRpc] private void UpdatePlayerPositionObserversRpc(int playerObjectId, Vector3 position) { // var player = InstanceFinder.ClientManager.Objects.Spawned[playerObjectId]; if (InstanceFinder.ClientManager.Objects.Spawned.TryGetValue(playerObjectId, out var playerObject)) playerObject.transform.position = position; else Debug.LogWarning("Player not found"); } public void UnloadScene() { // if (_stackedScenceHandle == 0) // return; // InstanceFinder.SceneManager.UnloadScene(_stackedScenceHandle); // _stackedScenceHandle = 0; } }