using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Unity.Mathematics; using UnityEngine; using static Unity.Mathematics.math; using Random = UnityEngine.Random; public class ZoneGeneratorTest : MonoBehaviour { public Galaxy Galaxy; public MeshRenderer ZoneBackground; public MeshRenderer ZoneBoundary; public ZoneObject ZoneObjectPrefab; public ParticleSystem BeltPrefab; public Texture2D PlanetSprite; public Texture2D GasGiantSprite; public Texture2D SunSprite; public float ZoneSizeScale = .01f; public float ZoneMassScale = .5f; public float ZoneMassPower = .33f; public float ZoneOrbitSpeed = 10; private DatabaseCache _cache; private Dictionary _zoneObjects = new Dictionary(); private Dictionary _zoneBelts = new Dictionary(); private List _wormholes = new List(); private Dictionary _orbitPositions = new Dictionary(); private GameContext _context; private Material _boundaryMaterial; // Determine orbital position recursively, caching parent positions to avoid repeated calculations private float2 GetOrbitPosition(Guid orbit) { // Root orbit is fixed at center if(orbit==Guid.Empty) return Unity.Mathematics.float2.zero; if (!_orbitPositions.ContainsKey(orbit)) { var orbitData = _cache.Get(orbit); _orbitPositions[orbit] = GetOrbitPosition(orbitData.Parent) + (orbitData.Period < .01f ? Unity.Mathematics.float2.zero : OrbitData.Evaluate(Time.time * ZoneOrbitSpeed / -orbitData.Period + orbitData.Phase) * orbitData.Distance); } var position = _orbitPositions[orbit]; if (float.IsNaN(position.x)) { Debug.Log("Orbit position is NaN, something went very wrong!"); return Unity.Mathematics.float2.zero; } return _orbitPositions[orbit]; } void Start() { _cache = new DatabaseCache(); _context = new GameContext(_cache, Debug.Log); _boundaryMaterial = ZoneBoundary.material; } void Update() { _orbitPositions.Clear(); foreach (var planet in _zoneObjects) { var planetData = _cache.Get(planet.Key); planet.Value.transform.position = (Vector2) GetOrbitPosition(planetData.Orbit) * ZoneSizeScale; } foreach (var belt in _zoneBelts) { var planetData = _cache.Get(belt.Key); belt.Value.transform.position = float3(GetOrbitPosition(_cache.Get(planetData.Orbit).Parent) * ZoneSizeScale, .15f); } if (Input.GetKeyDown(KeyCode.Space)) { PopulateZone(); } } void PopulateZone() { // Delete all the existing zone contents foreach (var zoneObject in _zoneObjects.Values) Destroy(zoneObject.gameObject);//zoneObject.GetComponent().ReturnToPool(); _zoneObjects.Clear(); foreach (var zoneObject in _wormholes) Destroy(zoneObject.gameObject); //zoneObject.GetComponent().ReturnToPool(); _wormholes.Clear(); foreach (var belt in _zoneBelts.Values) Destroy(belt.gameObject); _zoneBelts.Clear(); float2 position; do { position = float2(Random.value, Random.value); } while (Galaxy.MapData.StarDensity.Evaluate(position, Galaxy.MapData.GlobalData) < .1f); var zone = new ZoneData{Context = _context, Name = Guid.NewGuid().ToString(), Position = position}; OrbitData[] orbits; PlanetData[] planets; ZoneGenerator.GenerateZone( global: Galaxy.MapData.GlobalData, zone: zone, mapLayers: Galaxy.MapData.ResourceDensities, resources: Array.Empty(), orbitData: out orbits, planetsData: out planets); _cache.AddAll(orbits); _cache.AddAll(planets); _cache.Add(zone); float zoneDepth = 0; foreach (var planet in planets) { if (!planet.Belt) { var planetObject = Instantiate(ZoneObjectPrefab, transform); _zoneObjects[planet.ID] = planetObject; planetObject.Label.text = planet.Name; planetObject.GravityMesh.gameObject.SetActive(true); planetObject.GravityMesh.transform.localScale = Vector3.one * (pow(planet.Mass, Galaxy.MapData.GlobalData.GravityRadiusExponent) * Galaxy.MapData.GlobalData.GravityRadiusMultiplier * 2 * ZoneSizeScale); var depth = pow(planet.Mass, ZoneMassPower) * ZoneMassScale; if (depth > zoneDepth) zoneDepth = depth; planetObject.GravityMesh.material.SetFloat("_Depth", depth); planetObject.Icon.material.SetTexture("_MainTex", planet.Mass > Galaxy.MapData.GlobalData.SunMass ? SunSprite : planet.Mass > Galaxy.MapData.GlobalData.GasGiantMass ? GasGiantSprite : PlanetSprite); } else { var beltObject = Instantiate(BeltPrefab, transform); _zoneBelts[planet.ID] = beltObject; var orbit = _cache.Get(planet.Orbit); var beltEmission = beltObject.emission; beltEmission.rateOverTime = new ParticleSystem.MinMaxCurve(pow(planet.Mass,Galaxy.MapData.GlobalData.BeltMassExponent) / Galaxy.MapData.GlobalData.BeltMassRatio * orbit.Distance); var beltShape = beltObject.shape; beltShape.radius = orbit.Distance * ZoneSizeScale; beltShape.donutRadius = orbit.Distance * ZoneSizeScale / 2; var beltVelocity = beltObject.velocityOverLifetime; beltVelocity.orbitalZ = orbit.Distance * ZoneSizeScale / orbit.Period * ZoneOrbitSpeed; beltObject.Simulate(60); beltObject.Play(); } } var zoneRadius = (zone.Radius * ZoneSizeScale * 2); ZoneBackground.material.SetFloat("_ClipDistance", zoneRadius); ZoneBackground.material.SetFloat("_HeightRange", zoneDepth + _boundaryMaterial.GetFloat("_Depth")); ZoneBoundary.transform.localScale = Vector3.one * zoneRadius; } }