using UnityEngine; using System.Collections.Generic; using System; #if GAIA_PRO_PRESENT namespace Gaia { /// /// This component can be attached to the main camera / main character for a so called "floating point precision fix". Unity (& many other game engines) /// suffer from the problem that graphic and physics calculation can become imprecise after a certain distance from the world origin. When your scene exceeds roughly /// 5000 units into any direction it can happen that you see symptoms like: /// shadows flickering /// shaky physics /// issues in animations /// The floating point fix component combats this by shifting all GameObjects back to the origin after a certain threshold is reached. While this is barely noticeable for the player, /// it prevents such issues as mentioned above as the world never exceeds 5000 units because it is shifted back before things like these can happen. /// public class FloatingPointFix : MonoBehaviour { private static GaiaSessionManager m_sessionManager; private static GaiaSessionManager SessionManager { get { if (m_sessionManager == null) { m_sessionManager = GaiaSessionManager.GetSessionManager(false, false); } return m_sessionManager; } } /// /// Singleton instance /// private static FloatingPointFix instance = null; /// /// Returns the current Floating Point Fix Instance in the scene /// public static FloatingPointFix Instance { get { if (instance == null) instance = (FloatingPointFix)FindObjectOfType(typeof(FloatingPointFix)); if (instance == null && Application.isPlaying) Debug.LogError("No Floating Point Fix Instance could be found, please add a Floating Point Fix component to the main player / camera object."); return instance; } } /// /// Returns true if the Floating Point Fix is active in this scene /// public static bool IsActive { get { if (instance == null) instance = (FloatingPointFix)FindObjectOfType(typeof(FloatingPointFix)); return instance != null; } } /// /// The distance from origin at which the floating point fix shift will be performed. Whenever the object that contains the floating point fix component /// moves further than this distance from 0,0,0 all floating point fix members and sectors will be shifted back to the origin. /// public float threshold = 1000.0f; /// /// This vector3 represents the cumulative offset so far /// public Vector3 totalOffset = Vector3.zero; /// /// Makes sure we have a singleton and sets the sectors in the scene up for the floating point fix mode. /// void OnEnable() { //Singleton pattern if (instance == null) { instance = this; } else if (instance != this) { Destroy(gameObject); return; } } /// /// Adds a Floating Point Fix Member. Members are GameObjects that need to be shifted when the floating point fix shift occurs. /// Make sure to call "Remove Member" when your object gets destroyed. /// /// The member to add public void AddMember(FloatingPointFixMember member) { if (!TerrainLoaderManager.Instance.m_allFloatingPointFixMembers.Contains(member)) { TerrainLoaderManager.Instance.m_allFloatingPointFixMembers.Add(member); } } /// /// Removes a Floating Point Fix Member from the tracking list. Members are GameObjects that need to be shifted when the floating point fix shift occurs. /// /// The member to remove public void RemoveMember(FloatingPointFixMember member) { if (SessionManager!=null) { if (TerrainLoaderManager.Instance.m_allFloatingPointFixMembers.Contains(member)) { TerrainLoaderManager.Instance.m_allFloatingPointFixMembers.Remove(member); } } } /// /// Adds a particle system simulated in World Space to the tracking list. All Particle Systems included in here will have their particles shifted as well when the floating point fix shift occurs. /// /// The particle system to add public void AddWorldSpaceParticleSystem(ParticleSystem ps) { if (!TerrainLoaderManager.Instance.m_allWorldSpaceParticleSystems.Contains(ps)) { TerrainLoaderManager.Instance.m_allWorldSpaceParticleSystems.Add(ps); } } /// /// Removes a particle system simulated in World Space from the tracking list. /// /// The particle system to remove public void RemoveWorldSpaceParticleSystem(ParticleSystem ps) { if (SessionManager != null) { if (TerrainLoaderManager.Instance.m_allWorldSpaceParticleSystems.Contains(ps)) { TerrainLoaderManager.Instance.m_allWorldSpaceParticleSystems.Remove(ps); } } } /// /// Converts a Vector3 to its "real" / original position as if the floating point fix would not exist. /// /// The /// public Vector3 ConvertToOriginalSpace(Vector3 position) { return position += totalOffset; } void LateUpdate() { Vector3Double currentPosition = gameObject.transform.position; currentPosition.y = 0; if (currentPosition.magnitude > threshold) { TerrainLoaderManager.Instance.SetOrigin(currentPosition + TerrainLoaderManager.Instance.GetOrigin()); gameObject.transform.position = new Vector3(0f, transform.position.y, 0f); } } } } #endif