using System; using UnityEngine; using System.Collections; using UnityEngine.Serialization; #if UNITY_5_3 || UNITY_5_3_OR_NEWER using UnityEngine.SceneManagement; #endif namespace WorldStreamer2 { /// /// Collider streamer. /// public class ColliderStreamer : MonoBehaviour { /// /// The name of the scene. /// [Tooltip("Scene name that belongs to this collider.")] public string sceneName; /// /// The scene path. /// [Tooltip("Path where collider streamer should find scene which has to loaded after collider hit.")] public string scenePath; /// /// The scene game object. /// public GameObject sceneGameObject; /// /// The collider streamer manager. /// [HideInInspector] public ColliderStreamerManager colliderStreamerManager; /// /// The player only activate. /// [Tooltip("If it's checkboxed only player could activate collider to start loading, otherwise every physical hit could activate it.")] public bool playerOnlyActivate = true; /// /// The unload timer. /// [Tooltip("Time in seconds after which scene will be unloaded when \"Player\" or object that activate loading will left collider area.")] public float unloadTimer = 0; public enum State { Start, Ready, Loading, Loaded, Unloading, Unloaded } public State currentState = State.Start; private float _unloadTimeStart; public State CurrentState { get => currentState; set => currentState = value; } /// /// Start this instance adds to world mover and searches for collider streamer prefab. /// private void Awake() { Setup(); } private void Setup() { if (CurrentState != State.Start) return; colliderStreamerManager = GameObject.FindGameObjectWithTag(ColliderStreamerManager.COLLIDERSTREAMERMANAGERTAG).GetComponent(); colliderStreamerManager.AddColliderStreamer(this); CurrentState = State.Ready; } /// /// Sets the scene game object and moves it to collider streamer position /// /// Scene game object. public void SetSceneGameObject(GameObject sceneGameObject) { this.sceneGameObject = sceneGameObject; this.sceneGameObject.transform.position = transform.position; CurrentState = State.Loaded; } /// /// Raises the trigger enter event and loads collider scene /// /// Other. private void OnTriggerEnter(Collider other) { if (CurrentState == State.Start) Setup(); //Debug.Log($"On trigger enter {other.transform.name}", this); if (playerOnlyActivate && other.transform != colliderStreamerManager.player) return; if (CurrentState is State.Loading or State.Loaded) return; CurrentState = State.Loading; if (Streamer.loadingManager != null) { //Debug.Log($"Streamer load scene async {sceneName}", this); Streamer.loadingManager.LoadColliderAsync(this); } else { //Debug.Log($"SceneManager load scene async {sceneName}", this); SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive); } } /// /// Raises the trigger exit event, and destroys scene game object /// /// Other. private void OnTriggerExit(Collider other) { if (CurrentState is State.Unloading or State.Unloaded) return; if ((playerOnlyActivate && other.transform != colliderStreamerManager.player) || !sceneGameObject) return; CurrentState = State.Unloading; //Debug.Log($"Unload scene async {sceneGameObject.scene.name}", this); //Invoke(nameof(UnloadScene), unloadTimer); _unloadTimeStart = Time.time; } /// /// Update this instance. Unloads scene after unloadTimer seconds /// private void Update() { //if (_waitingForUnload) // Debug.Log($"time {Time.time} unloadTimeStart {_unloadTimeStart} {Time.time - _unloadTimeStart}", this); if (CurrentState == State.Unloading && Time.time - _unloadTimeStart > unloadTimer) UnloadScene(); } /// /// Unloads the scene. /// public void UnloadScene() { CurrentState = State.Unloaded; if (Streamer.loadingManager != null) { Streamer.loadingManager.UnloadColliderAsync(this); } else SceneManager.UnloadSceneAsync(sceneGameObject.scene); } } }