174 lines
5.5 KiB
C#
174 lines
5.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class OrbitalPosition
|
|
{
|
|
public Int64 pRing = 0;
|
|
public float DistanceFromCentre = 0;
|
|
public float RadiusDistance = 0;
|
|
|
|
public Transform owner = null;
|
|
|
|
public int m_SpinSpeed = 1;
|
|
public bool m_DeletedAtCentre = false;
|
|
|
|
public OrbitalPosition(GameObject _owner)
|
|
{
|
|
pRing = GlobalOrbitalPositionManager.LastRingID;
|
|
owner = _owner.transform;
|
|
}
|
|
|
|
public Vector3 TranslateToVec3() => new
|
|
(
|
|
x: DistanceFromCentre * Mathf.Cos(RadiusDistance),
|
|
y: DistanceFromCentre * Mathf.Sin(RadiusDistance)
|
|
);
|
|
}
|
|
|
|
public class Ring : MonoBehaviour
|
|
{
|
|
public Int64 ID;
|
|
}
|
|
|
|
public class GlobalOrbitalPositionManager : MonoBehaviour
|
|
{
|
|
static GlobalOrbitalPositionManager s_Instance = null;
|
|
private readonly List<OrbitalPosition> m_ObjectInstances = new();
|
|
private readonly List<Ring> m_Rings = new();
|
|
private readonly Dictionary<Int64, float> m_Distances = new();
|
|
|
|
private float m_TimeOfLastRingSpawn = float.NegativeInfinity;
|
|
|
|
private Int64 m_LastGeneratedRing = 0;
|
|
public static Int64 LastRingID => s_Instance.m_LastGeneratedRing;
|
|
|
|
public static float GetDistanceOf(Int64 rowID) => s_Instance.m_Distances[rowID];
|
|
private const int CIRCLE_POINTS = 360;
|
|
|
|
Vector3[] m_PrecalculatedPositions;
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void OnApplicationStart()
|
|
{
|
|
GameObject manager = new("GLOBAL ORBITAL MANAGER");
|
|
DontDestroyOnLoad(manager);
|
|
|
|
s_Instance = manager.AddComponent<GlobalOrbitalPositionManager>();
|
|
s_Instance.m_PrecalculatedPositions = new Vector3[CIRCLE_POINTS + 1];
|
|
|
|
for (int i = 0; i < CIRCLE_POINTS; i++)
|
|
{
|
|
s_Instance.m_PrecalculatedPositions[i] = new Vector3
|
|
(
|
|
x: Mathf.Cos(Mathf.Deg2Rad * i),
|
|
y: Mathf.Sin(Mathf.Deg2Rad * i),
|
|
z: 0
|
|
);
|
|
}
|
|
|
|
s_Instance.m_PrecalculatedPositions[CIRCLE_POINTS] = s_Instance.m_PrecalculatedPositions[0];
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (Time.time - m_TimeOfLastRingSpawn > GlobalOrbitalSettings.GapDistance)
|
|
{
|
|
GameObject newRing = Instantiate(GlobalOrbitalSettings.RingPrefab);
|
|
newRing.transform.localScale = new Vector3(10f, 10f, 1);
|
|
|
|
Ring ring = newRing.AddComponent<Ring>();
|
|
ring.ID = m_LastGeneratedRing + 1;
|
|
m_Rings.Add(ring);
|
|
|
|
LineRenderer renderer = newRing.GetComponentInChildren<LineRenderer>();
|
|
renderer.positionCount = CIRCLE_POINTS + 1;
|
|
renderer.startWidth = 0.1f;
|
|
renderer.endWidth = 0.1f;
|
|
renderer.material = new(Shader.Find("Sprites/Default"));
|
|
|
|
m_LastGeneratedRing = ring.ID;
|
|
m_TimeOfLastRingSpawn = Time.time;
|
|
}
|
|
|
|
List<Ring> toRemove = new();
|
|
int index = 0;
|
|
m_Distances.Clear();
|
|
|
|
foreach (Ring ring in m_Rings)
|
|
{
|
|
float diff = Time.deltaTime * GlobalOrbitalSettings.DistanceSpeed;
|
|
ring.transform.localScale -= new Vector3(diff, diff, 0f);
|
|
|
|
LineRenderer renderer = ring.GetComponentInChildren<LineRenderer>();
|
|
for (int vert = 0; vert < CIRCLE_POINTS + 1; vert++)
|
|
{
|
|
renderer.SetPosition(vert, m_PrecalculatedPositions[vert] * ring.transform.localScale.x);
|
|
}
|
|
|
|
float opacity = (ring.transform.localScale.x - 0.5f) / 4f;
|
|
opacity = Mathf.Clamp(opacity, 0, 0.5f);
|
|
if (ring.transform.localScale.x < 0.5f)
|
|
toRemove.Add(ring);
|
|
|
|
Color c = Color.white;
|
|
c.a = opacity;
|
|
|
|
renderer.startColor = c;
|
|
renderer.endColor = c;
|
|
|
|
m_Distances[ring.ID] = ring.transform.localScale.x;
|
|
index++;
|
|
}
|
|
|
|
foreach (Ring ring in toRemove)
|
|
{
|
|
m_Rings.Remove(ring);
|
|
Destroy(ring.gameObject);
|
|
}
|
|
|
|
foreach (OrbitalPosition orbitalPosition in m_ObjectInstances)
|
|
{
|
|
if (!m_Distances.ContainsKey(orbitalPosition.pRing))
|
|
{
|
|
if (orbitalPosition.m_DeletedAtCentre)
|
|
{
|
|
Destroy(orbitalPosition.owner.gameObject);
|
|
continue;
|
|
}
|
|
|
|
orbitalPosition.pRing = m_LastGeneratedRing;
|
|
}
|
|
|
|
float distance = m_Distances[orbitalPosition.pRing];
|
|
orbitalPosition.DistanceFromCentre = distance;
|
|
orbitalPosition.RadiusDistance = (orbitalPosition.RadiusDistance + (Time.deltaTime * GlobalOrbitalSettings.RadiusSpeed)) % (Mathf.PI * 2);
|
|
|
|
orbitalPosition.owner.position = orbitalPosition.TranslateToVec3();
|
|
}
|
|
}
|
|
|
|
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 virtual void OnStart() { }
|
|
}
|