using System; using System.Collections.Generic; using UnityEngine; namespace Utils { public class EndlessTerrain : MonoBehaviour { public const float ViewDistance = 300; public Transform viewer; public static Vector2 ViewerPosition; private int _chunkSize; private int _chunksVisibleInViewDistance; private Dictionary _terrainChunks = new(); private void Start() { _chunkSize = MapGenerator.ChunkSize - 1; _chunksVisibleInViewDistance = Mathf.RoundToInt(ViewDistance / _chunkSize); } private void Update() { ViewerPosition = new Vector2(viewer.position.x, viewer.position.z); UpdateVisibleChunks(); } private void UpdateVisibleChunks() { int currentChunkCoordX = Mathf.RoundToInt(ViewerPosition.x / _chunkSize); int currentChunkCoordY = Mathf.RoundToInt(ViewerPosition.y / _chunkSize); for (int yOffset = -_chunksVisibleInViewDistance; yOffset <= _chunksVisibleInViewDistance; yOffset++) for (int xOffset = -_chunksVisibleInViewDistance; xOffset <= _chunksVisibleInViewDistance;) { Vector2 viewedChunkCoord = new Vector2(currentChunkCoordX + xOffset, currentChunkCoordY + yOffset); if (_terrainChunks.ContainsKey(viewedChunkCoord)) _terrainChunks[viewedChunkCoord].UpdateTerrainChunk(); else _terrainChunks.Add(viewedChunkCoord, new TerrainChunk(viewedChunkCoord, _chunkSize)); } } private class TerrainChunk { public Vector2 Position; public GameObject MeshObject; public Bounds Bounds; public TerrainChunk(Vector2 coord, int size) { Position = coord * size; Bounds = new Bounds(Position, Vector3.one * size); Vector3 position = new Vector3(Position.x, 0, Position.y); MeshObject = GameObject.CreatePrimitive(PrimitiveType.Plane); MeshObject.transform.position = position; MeshObject.transform.localScale = Vector3.one * size / 10f; SetVisible(false); } public void UpdateTerrainChunk() { float viewerDistance = Mathf.Sqrt(Bounds.SqrDistance(ViewerPosition)); bool visible = viewerDistance <= ViewDistance; SetVisible(visible); } public void SetVisible(bool visible) { MeshObject.SetActive(visible); } } } }