using System.Collections.Generic; using UnityEngine; public class OrbitalPosition { public float DistanceFromCentre = 0; public float RadiusDistance = 0; public Transform owner = null; public OrbitalPosition(GameObject _owner) { owner = _owner.transform; } public Vector3 TranslateToVec3() => new ( x: DistanceFromCentre * Mathf.Cos(RadiusDistance), y: DistanceFromCentre * Mathf.Sin(RadiusDistance) ); } public class GlobalOrbitalPositionManager : MonoBehaviour { static GlobalOrbitalPositionManager s_Instance = null; private readonly List m_ObjectInstances = new(); private readonly List m_Rings = new(); private float m_TimeOfLastRingSpawn = float.NegativeInfinity; [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void OnApplicationStart() { GameObject manager = new("GLOBAL ORBITAL MANAGER"); DontDestroyOnLoad(manager); s_Instance = manager.AddComponent(); } public void Update() { if (Time.time - m_TimeOfLastRingSpawn > GlobalOrbitalSettings.GapDistance) { GameObject newRing = Instantiate(GlobalOrbitalSettings.RingPrefab); m_Rings.Add(newRing.transform); newRing.transform.localScale = new Vector3(10f, 10f, 1); m_TimeOfLastRingSpawn = Time.time; } foreach (OrbitalPosition orbitalPosition in m_ObjectInstances) { orbitalPosition.DistanceFromCentre = Mathf.Clamp(orbitalPosition.DistanceFromCentre - (Time.deltaTime * GlobalOrbitalSettings.DistanceSpeed), 0f, float.PositiveInfinity); orbitalPosition.RadiusDistance = (orbitalPosition.RadiusDistance + (Time.deltaTime * GlobalOrbitalSettings.RadiusSpeed)) % (Mathf.PI * 2); orbitalPosition.owner.position = orbitalPosition.TranslateToVec3(); } List toRemove = new(); foreach (Transform ring in m_Rings) { float diff = Time.deltaTime * GlobalOrbitalSettings.DistanceSpeed; ring.localScale -= new Vector3(diff, diff, 0f); if (ring.localScale.x < 0) { toRemove.Add(ring); } } foreach (Transform ring in toRemove) { m_Rings.Remove(ring); Destroy(ring.gameObject); } } public static void RegisterOrbitalPositionInstance(OrbitalPosition newInstance) => s_Instance.m_ObjectInstances.Add(newInstance); public static void UnregisterOrbitalPositionInstance(OrbitalPosition removedInstance) => s_Instance.m_ObjectInstances.Remove(removedInstance); } public abstract class OrbitalPositionBehaviour : MonoBehaviour { protected OrbitalPosition m_OrbitalPosition = null; private void Start() { m_OrbitalPosition = new OrbitalPosition(gameObject); GlobalOrbitalPositionManager.RegisterOrbitalPositionInstance(m_OrbitalPosition); OnStart(); } private void OnDestroy() => GlobalOrbitalPositionManager.UnregisterOrbitalPositionInstance(m_OrbitalPosition); public abstract void OnStart(); }