|
@@ -0,0 +1,97 @@
|
|
|
|
|
+using UnityEngine;
|
|
|
|
|
+using System.Collections.Generic;
|
|
|
|
|
+using Unity.VisualScripting;
|
|
|
|
|
+
|
|
|
|
|
+public class EndlessTerrain : MonoBehaviour
|
|
|
|
|
+{
|
|
|
|
|
+ public const float maxViewDst = 450f;
|
|
|
|
|
+ public Transform viewer;
|
|
|
|
|
+
|
|
|
|
|
+ public static Vector2 viewerPosition;
|
|
|
|
|
+ int chunkSize;
|
|
|
|
|
+ int chunksVisibleInViewDst;
|
|
|
|
|
+
|
|
|
|
|
+ Dictionary<Vector2, TerrainChunk> terrainChunkDictionnary = new Dictionary<Vector2, TerrainChunk>();
|
|
|
|
|
+ List<TerrainChunk> terrainChunksVisibleLastUpdate = new List<TerrainChunk>();
|
|
|
|
|
+
|
|
|
|
|
+ private void Start()
|
|
|
|
|
+ {
|
|
|
|
|
+ chunkSize = MapGenerator.mapChunkSize - 1;
|
|
|
|
|
+ chunksVisibleInViewDst = Mathf.RoundToInt(maxViewDst / chunkSize);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void Update()
|
|
|
|
|
+ {
|
|
|
|
|
+ viewerPosition = new(viewer.position.x, viewer.position.z);
|
|
|
|
|
+ UpdateVisibleChunks();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ void UpdateVisibleChunks()
|
|
|
|
|
+ {
|
|
|
|
|
+ for (int i = 0; i < terrainChunksVisibleLastUpdate.Count; i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ terrainChunksVisibleLastUpdate[i].SetVisible(false);
|
|
|
|
|
+ }
|
|
|
|
|
+ terrainChunksVisibleLastUpdate.Clear();
|
|
|
|
|
+
|
|
|
|
|
+ int currentChunkCoordX = Mathf.RoundToInt(viewerPosition.x / chunkSize);
|
|
|
|
|
+ int currentChunkCoordY = Mathf.RoundToInt(viewerPosition.y / chunkSize);
|
|
|
|
|
+
|
|
|
|
|
+ for (int yOffset = -chunksVisibleInViewDst; yOffset <=chunksVisibleInViewDst; yOffset++)
|
|
|
|
|
+ {
|
|
|
|
|
+ for (int xOffset = -chunksVisibleInViewDst; xOffset <= chunksVisibleInViewDst; xOffset++)
|
|
|
|
|
+ {
|
|
|
|
|
+ Vector2 viewedChunkCoord = new(currentChunkCoordX + xOffset, currentChunkCoordY + yOffset);
|
|
|
|
|
+
|
|
|
|
|
+ if (terrainChunkDictionnary.ContainsKey(viewedChunkCoord))
|
|
|
|
|
+ {
|
|
|
|
|
+ terrainChunkDictionnary[viewedChunkCoord].UpdateTerrainChunk();
|
|
|
|
|
+ if (terrainChunkDictionnary[viewedChunkCoord].IsVisible())
|
|
|
|
|
+ {
|
|
|
|
|
+ terrainChunksVisibleLastUpdate.Add(terrainChunkDictionnary[viewedChunkCoord]);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ terrainChunkDictionnary.Add(viewedChunkCoord, new TerrainChunk(viewedChunkCoord, chunkSize, transform));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public class TerrainChunk
|
|
|
|
|
+ {
|
|
|
|
|
+ GameObject meshObject;
|
|
|
|
|
+ Vector2 position;
|
|
|
|
|
+ Bounds bounds;
|
|
|
|
|
+ public TerrainChunk(Vector2 coord, int size, Transform parent)
|
|
|
|
|
+ {
|
|
|
|
|
+ position = coord * size;
|
|
|
|
|
+ bounds = new Bounds(position, Vector2.one * size);
|
|
|
|
|
+ Vector3 positionV3 = new(position.x, 0, position.y);
|
|
|
|
|
+
|
|
|
|
|
+ meshObject = GameObject.CreatePrimitive(PrimitiveType.Plane);
|
|
|
|
|
+ meshObject.transform.position = positionV3;
|
|
|
|
|
+ meshObject.transform.localScale = Vector3.one * size / 10f;
|
|
|
|
|
+ meshObject.transform.parent = parent;
|
|
|
|
|
+ SetVisible(false);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void UpdateTerrainChunk()
|
|
|
|
|
+ {
|
|
|
|
|
+ float viewDstFromNearestEdge = Mathf.Sqrt(bounds.SqrDistance(viewerPosition));
|
|
|
|
|
+ bool visible = viewDstFromNearestEdge <= maxViewDst;
|
|
|
|
|
+ SetVisible(visible);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void SetVisible(bool visible)
|
|
|
|
|
+ {
|
|
|
|
|
+ meshObject.SetActive(visible);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public bool IsVisible()
|
|
|
|
|
+ {
|
|
|
|
|
+ return meshObject.activeSelf;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|