You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
625 lines
23 KiB
C#
625 lines
23 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
using System;
|
|
using System.Linq;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
namespace Gaia
|
|
{
|
|
[ExecuteAlways]
|
|
public class GaiaScenePlayer : MonoBehaviour
|
|
{
|
|
public static GaiaScenePlayer Instance
|
|
{
|
|
get
|
|
{
|
|
if (m_instance == null)
|
|
{
|
|
m_instance = FindObjectOfType<GaiaScenePlayer>();
|
|
}
|
|
|
|
return m_instance;
|
|
}
|
|
}
|
|
|
|
[SerializeField] private static GaiaScenePlayer m_instance;
|
|
|
|
public GameObject m_gaiaUI;
|
|
public List<GameObject> m_gaiaCreatedControllers = new List<GameObject>();
|
|
|
|
private Camera m_camera;
|
|
private Bounds m_worldSpaceBounds = new Bounds();
|
|
private Plane[] m_planes = new Plane[6];
|
|
private Terrain[] m_allTerrains = new Terrain[0];
|
|
private MeshRenderer[] m_allTerrainMeshRenderers = new MeshRenderer[0];
|
|
|
|
private void Start()
|
|
{
|
|
m_instance = this;
|
|
if (!GaiaUtils.CheckIfSceneProfileExists())
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_camera = GaiaGlobal.Instance.m_mainCamera;
|
|
m_allTerrains = Terrain.activeTerrains;
|
|
|
|
//Collect all Mesh Terrains that are present at startup
|
|
List<MeshRenderer> tempMeshRenderers = new List<MeshRenderer>();
|
|
|
|
for (int i = 0; i < SceneManager.sceneCount; i++)
|
|
{
|
|
Scene scene = SceneManager.GetSceneAt(i);
|
|
if (scene.isLoaded)
|
|
{
|
|
foreach (GameObject go in scene.GetRootGameObjects())
|
|
{
|
|
AddTerrainMeshRenderer(go, tempMeshRenderers);
|
|
}
|
|
}
|
|
}
|
|
m_allTerrainMeshRenderers = tempMeshRenderers.ToArray();
|
|
|
|
|
|
if (GaiaGlobal.Instance.SceneProfile.m_terrainCullingEnabled)
|
|
{
|
|
SceneManager.sceneLoaded -= OnSceneLoaded;
|
|
SceneManager.sceneLoaded += OnSceneLoaded;
|
|
SceneManager.sceneUnloaded -= OnSceneUnLoaded;
|
|
SceneManager.sceneUnloaded += OnSceneUnLoaded;
|
|
}
|
|
else
|
|
{
|
|
SceneManager.sceneLoaded -= OnSceneLoaded;
|
|
SceneManager.sceneUnloaded -= OnSceneUnLoaded;
|
|
}
|
|
|
|
GaiaAPI.RefreshCameraCulling();
|
|
|
|
if (Application.isPlaying)
|
|
{
|
|
if (m_gaiaUI != null)
|
|
{
|
|
m_gaiaUI.SetActive(true);
|
|
}
|
|
}
|
|
}
|
|
private void Update()
|
|
{
|
|
if (!Application.isPlaying)
|
|
{
|
|
return;
|
|
}
|
|
if (!GaiaUtils.CheckIfSceneProfileExists())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!GaiaGlobal.Instance.SceneProfile.m_terrainCullingEnabled || m_camera == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GeometryUtility.CalculateFrustumPlanes(m_camera, m_planes);
|
|
if (GaiaGlobal.Instance.SceneProfile.m_terrainCullingEnabled)
|
|
{
|
|
for (int i = 0; i < m_allTerrains.Length; i++)
|
|
{
|
|
Terrain terrain = m_allTerrains[i];
|
|
if (terrain == null)
|
|
{
|
|
continue;
|
|
}
|
|
//Check needs to performed in world space, terrain bounds are in local space of the terrain
|
|
m_worldSpaceBounds = terrain.terrainData.bounds;
|
|
m_worldSpaceBounds.center = new Vector3(m_worldSpaceBounds.center.x + terrain.transform.position.x, m_worldSpaceBounds.center.y + terrain.transform.position.y, m_worldSpaceBounds.center.z + terrain.transform.position.z);
|
|
|
|
if (GeometryUtility.TestPlanesAABB(m_planes, m_worldSpaceBounds))
|
|
{
|
|
terrain.drawHeightmap = true;
|
|
terrain.drawTreesAndFoliage = true;
|
|
|
|
//Deactivate terrain GO entirely
|
|
//terrain.gameObject.SetActive(true);
|
|
|
|
//Activate object spawns
|
|
//Transform spawnsTransform = terrain.gameObject.transform.Find(GaiaConstants.defaultGOSpawnTarget);
|
|
//spawnsTransform.gameObject.SetActive(true);
|
|
}
|
|
else
|
|
{
|
|
terrain.drawHeightmap = false;
|
|
terrain.drawTreesAndFoliage = false;
|
|
|
|
//Deactivate terrain GO entirely
|
|
//terrain.gameObject.SetActive(false);
|
|
|
|
//Deactivate object spawns
|
|
//Transform spawnsTransform = terrain.gameObject.transform.Find(GaiaConstants.defaultGOSpawnTarget);
|
|
//spawnsTransform.gameObject.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (GaiaGlobal.Instance.SceneProfile.m_terrainCullingEnabled)
|
|
{
|
|
for (int i = 0; i < m_allTerrainMeshRenderers.Length; i++)
|
|
{
|
|
MeshRenderer mr = m_allTerrainMeshRenderers[i];
|
|
if (mr != null)
|
|
{
|
|
if (GeometryUtility.TestPlanesAABB(m_planes, mr.bounds))
|
|
{
|
|
mr.enabled = true;
|
|
}
|
|
else
|
|
{
|
|
mr.enabled = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
private void OnDestroy()
|
|
{
|
|
SceneManager.sceneLoaded -= OnSceneLoaded;
|
|
SceneManager.sceneUnloaded -= OnSceneUnLoaded;
|
|
}
|
|
private void OnValidate()
|
|
{
|
|
m_instance = this;
|
|
|
|
if (!GaiaUtils.CheckIfSceneProfileExists())
|
|
{
|
|
return;
|
|
}
|
|
|
|
GaiaAPI.RefreshCameraCulling();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a controller to the stored data
|
|
/// </summary>
|
|
/// <param name="controllerObject"></param>
|
|
public static void AddControllerObject(GameObject controllerObject)
|
|
{
|
|
GaiaScenePlayer gaiaPlayer = Instance;
|
|
if (gaiaPlayer != null)
|
|
{
|
|
if (controllerObject != null)
|
|
{
|
|
gaiaPlayer.m_gaiaCreatedControllers.Add(controllerObject);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Removes all the controllers
|
|
/// Returns the player controller
|
|
/// </summary>
|
|
/// <param name="checkForCustomControllerComponent"></param>
|
|
public static GameObject RemoveAllControllers(bool checkForCustomControllerComponent)
|
|
{
|
|
GameObject playerObject = null;
|
|
GaiaScenePlayer gaiaPlayer = Instance;
|
|
if (gaiaPlayer != null)
|
|
{
|
|
if (gaiaPlayer.m_gaiaCreatedControllers.Count == 0)
|
|
{
|
|
Transform[] otherTransforms = gaiaPlayer.GetComponentsInChildren<Transform>();
|
|
if (otherTransforms.Length > 0)
|
|
{
|
|
foreach (Transform otherTransform in otherTransforms)
|
|
{
|
|
if (otherTransform != gaiaPlayer.transform)
|
|
{
|
|
AddControllerObject(otherTransform.gameObject);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (gaiaPlayer.m_gaiaCreatedControllers.Count > 0)
|
|
{
|
|
foreach (GameObject controller in gaiaPlayer.m_gaiaCreatedControllers)
|
|
{
|
|
if (controller != null)
|
|
{
|
|
if (checkForCustomControllerComponent)
|
|
{
|
|
CustomGaiaController customController = controller.GetComponent<CustomGaiaController>();
|
|
if (customController != null)
|
|
{
|
|
if (customController.m_isPlayer)
|
|
{
|
|
playerObject = controller;
|
|
}
|
|
}
|
|
|
|
DestroyImmediate(controller);
|
|
}
|
|
else
|
|
{
|
|
if (!controller.TryGetComponent(out Camera camera))
|
|
{
|
|
playerObject = controller;
|
|
}
|
|
|
|
DestroyImmediate(controller);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
gaiaPlayer.m_gaiaCreatedControllers.Clear();
|
|
}
|
|
|
|
return playerObject;
|
|
}
|
|
|
|
private void AddTerrainMeshRenderer(GameObject go, List<MeshRenderer> meshRenderers)
|
|
{
|
|
if (IsSingleMeshTerrain(go))
|
|
{
|
|
MeshRenderer mr = go.GetComponent<MeshRenderer>();
|
|
if (mr != null)
|
|
{
|
|
if (!meshRenderers.Contains(mr) && !m_allTerrainMeshRenderers.Contains(mr))
|
|
{
|
|
meshRenderers.Add(mr);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (IsMeshLODTerrain(go))
|
|
{
|
|
LODGroup lg = go.GetComponent<LODGroup>();
|
|
foreach (LOD lod in lg.GetLODs())
|
|
{
|
|
foreach (Renderer renderer in lod.renderers)
|
|
{
|
|
if (renderer != null && renderer.GetType() == typeof(MeshRenderer))
|
|
{
|
|
MeshRenderer mr = (MeshRenderer)renderer;
|
|
|
|
if (!meshRenderers.Contains(mr))
|
|
{
|
|
meshRenderers.Add((MeshRenderer)mr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private bool IsSingleMeshTerrain(GameObject go)
|
|
{
|
|
//Two possible things to find here: terrains that have been converted to a single mesh terrain or impostor terrains WITHOUT a LOD Group.
|
|
string searchString = GaiaConstants.MeshTerrainName;
|
|
string searchString2 = GaiaConstants.ImpostorTerrainName;
|
|
if (go.name.StartsWith(searchString) || (go.name.StartsWith(searchString2) && go.GetComponent<LODGroup>() == null))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
private bool IsMeshLODTerrain(GameObject go)
|
|
{
|
|
//Two possible things to find here: terrains that have been converted to a mesh terrain with a LOD Group, or impostor terrains with a LOD Group.
|
|
string searchString1 = GaiaConstants.MeshTerrainLODGroupPrefix;
|
|
string searchString2 = GaiaConstants.ImpostorTerrainName;
|
|
if (go.name.StartsWith(searchString1) || (go.name.StartsWith(searchString2) && go.GetComponent<LODGroup>()!=null))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
//Terrain Culling
|
|
private void OnSceneUnLoaded(Scene scene)
|
|
{
|
|
Invoke("UpdateTerrains", 0.5f);
|
|
|
|
m_allTerrainMeshRenderers = m_allTerrainMeshRenderers.Where(x => x != null).ToArray();
|
|
|
|
|
|
|
|
}
|
|
private void OnSceneLoaded(Scene scene, LoadSceneMode arg1)
|
|
{
|
|
Invoke("UpdateTerrains", 0.5f);
|
|
List<MeshRenderer> tempMeshRenderers = new List<MeshRenderer>();
|
|
foreach (GameObject go in scene.GetRootGameObjects())
|
|
{
|
|
AddTerrainMeshRenderer(go, tempMeshRenderers);
|
|
}
|
|
m_allTerrainMeshRenderers = m_allTerrainMeshRenderers.Concat(tempMeshRenderers).ToArray();
|
|
}
|
|
private void UpdateTerrains()
|
|
{
|
|
m_allTerrains = Terrain.activeTerrains;
|
|
}
|
|
//Camera Culling
|
|
public static void UpdateCullingDistances()
|
|
{
|
|
if (!GaiaUtils.CheckIfSceneProfileExists())
|
|
{
|
|
return;
|
|
}
|
|
|
|
SceneProfile sceneProfile = GaiaGlobal.Instance.SceneProfile;
|
|
if (sceneProfile.CullingProfile == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GaiaSceneCullingProfile cullingProfile = sceneProfile.CullingProfile;
|
|
#if GAIA_PRO_PRESENT
|
|
if (ProceduralWorldsGlobalWeather.Instance != null)
|
|
{
|
|
if (ProceduralWorldsGlobalWeather.Instance.CheckIsNight())
|
|
{
|
|
sceneProfile.m_sunLight = ProceduralWorldsGlobalWeather.Instance.m_moonLight;
|
|
}
|
|
else
|
|
{
|
|
sceneProfile.m_sunLight = ProceduralWorldsGlobalWeather.Instance.m_sunLight;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (sceneProfile.m_sunLight == null)
|
|
{
|
|
sceneProfile.m_sunLight = GaiaUtils.GetMainDirectionalLight(false);
|
|
}
|
|
}
|
|
#else
|
|
if (sceneProfile.m_sunLight == null)
|
|
{
|
|
sceneProfile.m_sunLight = GaiaUtils.GetMainDirectionalLight();
|
|
}
|
|
#endif
|
|
|
|
//Make sure we have distances
|
|
if (cullingProfile.m_layerDistances == null || cullingProfile.m_layerDistances.Length != 32)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sceneProfile.m_enableLayerCulling)
|
|
{
|
|
//Apply to main camera
|
|
float[] newCullingDistance = new float[32];
|
|
for (int i = 0; i < newCullingDistance.Length; i++)
|
|
{
|
|
newCullingDistance[i] = cullingProfile.m_layerDistances[i];
|
|
if (newCullingDistance[i] != 0f)
|
|
{
|
|
if (cullingProfile.m_additionalCullingDistance >= 0)
|
|
{
|
|
newCullingDistance[i] += cullingProfile.m_additionalCullingDistance;
|
|
}
|
|
else
|
|
{
|
|
newCullingDistance[i] -= Mathf.Abs(cullingProfile.m_additionalCullingDistance);
|
|
Mathf.Clamp(newCullingDistance[i], 0.01f, Mathf.Infinity);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (GaiaGlobal.Instance.m_mainCamera != null)
|
|
{
|
|
GaiaGlobal.Instance.m_mainCamera.layerCullDistances = newCullingDistance;
|
|
}
|
|
|
|
//Apply to sun/moon light
|
|
float[] newShadowCullingDistance = new float[32];
|
|
for (int i = 0; i < newShadowCullingDistance.Length; i++)
|
|
{
|
|
newShadowCullingDistance[i] = cullingProfile.m_shadowLayerDistances[i];
|
|
if (newShadowCullingDistance[i] != 0f)
|
|
{
|
|
if (cullingProfile.m_additionalCullingDistance >= 0)
|
|
{
|
|
newShadowCullingDistance[i] += cullingProfile.m_additionalCullingDistance;
|
|
}
|
|
else
|
|
{
|
|
newShadowCullingDistance[i] -= Mathf.Abs(cullingProfile.m_additionalCullingDistance);
|
|
Mathf.Clamp(newShadowCullingDistance[i], 0.01f, Mathf.Infinity);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (sceneProfile.m_sunLight != null)
|
|
{
|
|
sceneProfile.m_sunLight.layerShadowCullDistances = newShadowCullingDistance;
|
|
}
|
|
|
|
if (sceneProfile.m_moonLight != null)
|
|
{
|
|
sceneProfile.m_moonLight.layerShadowCullDistances = newShadowCullingDistance;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
float[] layerCulls = new float[32];
|
|
for (int i = 0; i < layerCulls.Length; i++)
|
|
{
|
|
layerCulls[i] = 0f;
|
|
}
|
|
|
|
//Apply to main camera
|
|
if (GaiaGlobal.Instance.m_mainCamera != null)
|
|
{
|
|
GaiaGlobal.Instance.m_mainCamera.layerCullDistances = layerCulls;
|
|
}
|
|
|
|
//Apply to sun/moon light
|
|
if (sceneProfile.m_sunLight != null)
|
|
{
|
|
sceneProfile.m_sunLight.layerShadowCullDistances = layerCulls;
|
|
}
|
|
if (sceneProfile.m_moonLight != null)
|
|
{
|
|
sceneProfile.m_moonLight.layerShadowCullDistances = layerCulls;
|
|
}
|
|
}
|
|
}
|
|
public static void ApplySceneSetup(bool active)
|
|
{
|
|
//Apply to editor camera
|
|
#if UNITY_EDITOR
|
|
SceneProfile sceneProfile = GaiaGlobal.Instance.SceneProfile;
|
|
if (sceneProfile.m_enableLayerCulling)
|
|
{
|
|
GaiaSceneCullingProfile cullingProfile = sceneProfile.CullingProfile;
|
|
if (cullingProfile != null)
|
|
{
|
|
if (active)
|
|
{
|
|
foreach (var sceneCamera in SceneView.GetAllSceneCameras())
|
|
{
|
|
float[] newCullingDistance = new float[32];
|
|
for (int i = 0; i < newCullingDistance.Length; i++)
|
|
{
|
|
newCullingDistance[i] = cullingProfile.m_layerDistances[i];
|
|
if (cullingProfile.m_additionalCullingDistance >= 0)
|
|
{
|
|
newCullingDistance[i] += cullingProfile.m_additionalCullingDistance;
|
|
}
|
|
else
|
|
{
|
|
newCullingDistance[i] -= Mathf.Abs(cullingProfile.m_additionalCullingDistance);
|
|
Mathf.Clamp(newCullingDistance[i], 0.01f, Mathf.Infinity);
|
|
}
|
|
}
|
|
|
|
sceneCamera.layerCullDistances = newCullingDistance;
|
|
}
|
|
|
|
|
|
float[] newShadowCullingDistance = new float[32];
|
|
for (int i = 0; i < newShadowCullingDistance.Length; i++)
|
|
{
|
|
newShadowCullingDistance[i] = cullingProfile.m_shadowLayerDistances[i];
|
|
if (cullingProfile.m_additionalCullingDistance >= 0)
|
|
{
|
|
newShadowCullingDistance[i] += cullingProfile.m_additionalCullingDistance;
|
|
}
|
|
else
|
|
{
|
|
newShadowCullingDistance[i] -= Mathf.Abs(cullingProfile.m_additionalCullingDistance);
|
|
Mathf.Clamp(newShadowCullingDistance[i], 0.01f, Mathf.Infinity);
|
|
}
|
|
}
|
|
|
|
if (sceneProfile.m_sunLight != null)
|
|
{
|
|
sceneProfile.m_sunLight.layerShadowCullDistances = newShadowCullingDistance;
|
|
}
|
|
|
|
if (sceneProfile.m_moonLight != null)
|
|
{
|
|
sceneProfile.m_moonLight.layerShadowCullDistances = newShadowCullingDistance;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (var sceneCamera in SceneView.GetAllSceneCameras())
|
|
{
|
|
float[] layers = new float[32];
|
|
for (int i = 0; i < layers.Length; i++)
|
|
{
|
|
layers[i] = 0f;
|
|
}
|
|
|
|
sceneCamera.layerCullDistances = layers;
|
|
}
|
|
|
|
if (sceneProfile.m_sunLight != null)
|
|
{
|
|
float[] layers = new float[32];
|
|
for (int i = 0; i < layers.Length; i++)
|
|
{
|
|
layers[i] = 0f;
|
|
}
|
|
|
|
sceneProfile.m_sunLight.layerShadowCullDistances = layers;
|
|
}
|
|
|
|
if (sceneProfile.m_moonLight != null)
|
|
{
|
|
float[] layers = new float[32];
|
|
for (int i = 0; i < layers.Length; i++)
|
|
{
|
|
layers[i] = 0f;
|
|
}
|
|
|
|
sceneProfile.m_moonLight.layerShadowCullDistances = layers;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (var sceneCamera in SceneView.GetAllSceneCameras())
|
|
{
|
|
float[] layers = new float[32];
|
|
for (int i = 0; i < layers.Length; i++)
|
|
{
|
|
layers[i] = 0f;
|
|
}
|
|
|
|
sceneCamera.layerCullDistances = layers;
|
|
}
|
|
|
|
if (sceneProfile.m_sunLight != null)
|
|
{
|
|
float[] layers = new float[32];
|
|
for (int i = 0; i < layers.Length; i++)
|
|
{
|
|
layers[i] = 0f;
|
|
}
|
|
sceneProfile.m_sunLight.layerShadowCullDistances = layers;
|
|
}
|
|
|
|
if (sceneProfile.m_moonLight != null)
|
|
{
|
|
float[] layers = new float[32];
|
|
for (int i = 0; i < layers.Length; i++)
|
|
{
|
|
layers[i] = 0f;
|
|
}
|
|
sceneProfile.m_moonLight.layerShadowCullDistances = layers;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
//Controller Setup
|
|
/// <summary>
|
|
/// Sets the current controller type
|
|
/// </summary>
|
|
/// <param name="type"></param>
|
|
public static void SetCurrentControllerType(GaiaConstants.EnvironmentControllerType type)
|
|
{
|
|
LocationSystem system = FindObjectOfType<LocationSystem>();
|
|
if (system != null)
|
|
{
|
|
if (system.m_locationProfile != null)
|
|
{
|
|
system.m_locationProfile.m_currentControllerType = type;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |