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);
}
}
}