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 terrainChunkDictionnary = new Dictionary(); List terrainChunksVisibleLastUpdate = new List(); 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; } } }