Files
HauntedBloodlines/Assets/Scripts/Managers/DynamicSceneManager.cs
2025-05-29 22:31:40 +03:00

256 lines
7.9 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class DynamicSceneManager : MonoBehaviour
{
private static DynamicSceneManager _instance;
public static DynamicSceneManager GetInstance() { return _instance; }
private Dictionary<GameObject, bool> originalChunkStates = new Dictionary<GameObject, bool>();
public HashSet<string> loadedScenes = new HashSet<string>(); // Track loaded scenes
private void Awake()
{
if (_instance == null)
{
_instance = this;
DontDestroyOnLoad(gameObject); // This ensures the object persists across scene loads
}
else
{
Destroy(gameObject); // This prevents duplicate instances
}
//foreach (string nearbyScene in RoomManager.GetInstance()._nearbyRoomSceneNames)
//{
// RetainScene(nearbyScene);
//}
}
public void EnableChunks(List<GameObject> chunksToEnable, string sceneName)
{
Debug.Log($"Starting gradual enabling of {chunksToEnable.Count} chunks for scene {sceneName}");
foreach (var chunk in chunksToEnable)
{
if (!originalChunkStates.ContainsKey(chunk))
{
originalChunkStates[chunk] = chunk.activeSelf; // store initial state
}
}
if (!SceneManager.GetSceneByName(sceneName).isLoaded)
{
Debug.Log($"Scene {sceneName} is not loaded. Loading it now.");
LoadSceneAsync(sceneName, chunksToEnable);
}
else
{
Debug.Log($"Scene {sceneName} is already loaded. Enabling valid chunks.");
StartCoroutine(GradualEnableChunks(chunksToEnable));
}
}
public void DisableChunksExcept(List<GameObject> chunksToKeep, string sceneName)
{
Debug.Log($"Disabling chunks for scene: {sceneName}, keeping {chunksToKeep.Count} chunks.");
if (!IsSceneLoaded(sceneName))
{
Debug.LogWarning($"Attempted to disable chunks for an unloaded scene: {sceneName}");
return;
}
List<GameObject> chunksToDisable = new List<GameObject>();
foreach (GameObject rootObject in SceneManager.GetSceneByName(sceneName).GetRootGameObjects())
{
foreach (Transform child in rootObject.GetComponentsInChildren<Transform>(true))
{
if (!chunksToKeep.Contains(child.gameObject) && child.gameObject.activeSelf)
{
chunksToDisable.Add(child.gameObject);
}
}
}
//
// StartCoroutine(GradualUnloadChunks(chunksToDisable, sceneName));
}
private IEnumerator GradualLoadChunks(List<GameObject> chunksToEnable)
{
foreach (GameObject chunk in chunksToEnable)
{
if (chunk != null && !chunk.activeSelf)
{
chunk.SetActive(true);
Debug.Log($"Enabled chunk: {chunk.name}");
yield return null; // Distribute work across frames
}
}
}
private IEnumerator GradualEnableChunks(List<GameObject> chunksToEnable)
{
foreach (GameObject chunk in chunksToEnable)
{
if (chunk != null && !chunk.activeSelf)
{
if (originalChunkStates.ContainsKey(chunk) && originalChunkStates[chunk])
{
chunk.SetActive(true);
Debug.Log($"Enabled chunk: {chunk.name}");
}
else
{
Debug.Log($"Skipping chunk {chunk.name} - was originally inactive");
}
yield return null;
}
}
}
private void GradualUnloadChunks(List<GameObject> chunksToUnload)
{
StartCoroutine(GradualDisableChunks(chunksToUnload));
}
private IEnumerator GradualDisableChunks(List<GameObject> chunksToUnload)
{
foreach (GameObject chunk in chunksToUnload)
{
if (chunk != null && chunk.activeSelf)
{
chunk.SetActive(false);
Debug.Log($"Disabled chunk: {chunk.name}");
yield return null; // Spread disabling chunks across frames
}
}
}
public void RetainScene(string sceneName)
{
if (SceneManager.GetSceneByName(sceneName).isLoaded)
{
Debug.Log($"Scene {sceneName} is already loaded. Skipping RetainScene.");
loadedScenes.Add(sceneName);
return;
}
// Add to loadedScenes list and load the scene
if (!loadedScenes.Contains(sceneName))
loadedScenes.Add(sceneName);
SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
Debug.Log($"Scene {sceneName} retained successfully.");
}
public void RetainScenes(List<string> nearbyScenes)
{
if (nearbyScenes == null || nearbyScenes.Count == 0)
{
Debug.LogWarning("RetainScenes called with an empty or null list. No scenes retained.");
return;
}
nearbyScenes.RemoveAll(scene => string.IsNullOrWhiteSpace(scene)); // Αφαίρεση άδειων ή μη έγκυρων ονομάτων
foreach (string sceneName in nearbyScenes)
{
if (!loadedScenes.Contains(sceneName))
{
RetainScene(sceneName);
}
else
{
Debug.Log($"Scene {sceneName} is already loaded. Skipping.");
}
}
// Handle unloading as before
var scenesToUnload = new HashSet<string>(loadedScenes);
scenesToUnload.ExceptWith(nearbyScenes);
foreach (string sceneName in scenesToUnload)
{
Debug.Log($"Unloading scene: {sceneName}");
UnloadSceneAsync(sceneName);
}
}
public void ReleaseScenes(List<string> nearbyScenes)
{
var scenesToUnload = new HashSet<string>(loadedScenes);
// Retain nearby scenes
scenesToUnload.ExceptWith(nearbyScenes);
foreach (string sceneName in scenesToUnload)
{
Debug.Log($"Unloading scene: {sceneName}");
UnloadSceneAsync(sceneName);
}
}
private void LoadSceneAsync(string sceneName, List<GameObject> chunksToEnable = null)
{
SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive).completed += (op) =>
{
if (op.isDone)
{
loadedScenes.Add(sceneName);
Debug.Log($"Scene {sceneName} successfully loaded.");
if (chunksToEnable != null)
{
StartCoroutine(GradualEnableChunks(chunksToEnable));
}
}
};
}
public void UnloadSceneAsync(string sceneName)
{
if (string.IsNullOrEmpty(sceneName))
{
Debug.LogError("Cannot unload scene: Scene name is null or empty.");
return;
}
if (loadedScenes == null)
{
Debug.LogError("loadedScenes list is null!");
return;
}
if (loadedScenes.Contains(sceneName))
{
Debug.Log($"Attempting to unload scene: {sceneName}");
SceneManager.UnloadSceneAsync(sceneName).completed += op =>
{
if (op.isDone)
{
loadedScenes.Remove(sceneName);
Debug.Log($"Scene {sceneName} successfully unloaded.");
}
};
}
else
{
Debug.LogWarning($"Scene {sceneName} is not loaded. Cannot unload.");
}
}
public bool IsSceneLoaded(string sceneName)
{
return loadedScenes.Contains(sceneName);
}
public HashSet<string> GetLoadedScenes()
{
return new HashSet<string>(loadedScenes);
}
}