diff --git a/Assets/Scripts/TerrainGeneration/TerrainGenerator.cs b/Assets/Scripts/TerrainGeneration/TerrainGenerator.cs index 7c29e1562478bd08e45982a58d82abcf9a59213f..0dfe74af70958562f28acffc041a45f5161be28c 100644 --- a/Assets/Scripts/TerrainGeneration/TerrainGenerator.cs +++ b/Assets/Scripts/TerrainGeneration/TerrainGenerator.cs @@ -41,18 +41,29 @@ public class TerrainGenerator : MonoBehaviour [Tooltip("How tall the terrain is. May be changed to allow for higher terrains.")] public float terrainHeight = 600; + [Tooltip("What percentage of threads available should we use?")] + public float threadsUsage = 0.7f; + + public int MaxThreads => Mathf.FloorToInt(Environment.ProcessorCount * threadsUsage); + + [Header("Autogenerated values")] [Tooltip("Which terrain grid are we on right now?")] public Vector2Int currentGridPosition; + [Tooltip("Array of terrains to reuse.")] + public Terrain[] terrains = new Terrain[9]; + [Tooltip("Dictionary of previously loaded terrains.")] public Dictionary<Vector2Int, TerrainData> previouslyLoaded = new(); - public Queue<TerrainGenThread> threadsToRun = new(); + public Queue<TerrainGenThread> queuedThreads = new(); public ConcurrentBag<TerrainGenThread> completedGenerators = new(); - public int threadsCount = 0; + + [Header("Stats")] + public int runningThreads = 0; /// <summary> /// Apply the terrain that was generated by genThread. @@ -78,24 +89,29 @@ public class TerrainGenerator : MonoBehaviour if (!previouslyLoaded.ContainsKey(gridPos) || forceRefresh) { TerrainData data = Instantiate(Resources.Load<TerrainData>("Template")); - TerrainGenThread genThread = new(this, data, crawlPos, gridPos); + TerrainGenThread tGenThread = new(this, data, crawlPos, gridPos); + previouslyLoaded[gridPos] = data; - threadsCount++; - - if (threadsCount >= Environment.ProcessorCount) + if (runningThreads >= MaxThreads) { - threadsToRun.Enqueue(genThread); + // Too many threads. + queuedThreads.Enqueue(tGenThread); } else { - ThreadStart starter = new(genThread.Generate); - Thread thread = new(starter); - previouslyLoaded[gridPos] = data; - thread.Start(); + StartThread(tGenThread); } } } + private void StartThread(TerrainGenThread tGenThread) + { + runningThreads++; + ThreadStart starter = new(tGenThread.Generate); + Thread thread = new(starter); + thread.Start(); + } + public virtual void GenerateSurronding(Vector2 initCrawlPos, bool forceRefresh = false) { int count = 0; @@ -113,6 +129,7 @@ public class TerrainGenerator : MonoBehaviour private void Update() { + // Check for refresh. if (refresh) { refresh = false; @@ -123,10 +140,33 @@ public class TerrainGenerator : MonoBehaviour GenerateSurronding(crawlStartPosition, true); } - if (completedGenerators.TryTake(out TerrainGenThread tGenThread)) + // Check for queued threads. + if (queuedThreads.TryDequeue(out TerrainGenThread queuedThread) + && runningThreads < MaxThreads) { - ApplyGeneratedTerrain(tGenThread); - threadsCount--; + StartThread(queuedThread); } + + // Check for completed generators. + if (completedGenerators.TryTake(out TerrainGenThread completedThread)) + { + ApplyGeneratedTerrain(completedThread); + runningThreads--; + } + } + + /// <summary> + /// Gets the square distance between two points. + /// If A is located at (0,0) and B is located at (5,-10), + /// the distance would be 5+10=15. + /// </summary> + /// <param name="a">A position on the grid.</param> + /// <param name="b">Another position.</param> + /// <returns></returns> + public int SquareDistance(Vector2Int a, Vector2Int b) + { + Vector2Int diff = b - a; + + return Mathf.Abs(diff.x) + Mathf.Abs(diff.y); } }