| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- public class EndlessTerrain : MonoBehaviour
- {
- public const float maxViewDist = 450;
- public Transform viewer;
- public Material mapMaterial;
- public static Vector2 viewerPosition;
- static MapGenerator mapGenerator;
- int chunkSize;
- int chunksVisibleInViewDst;
- Dictionary<Vector2, TerrainChunk> terrainChunkDictionary = new Dictionary<Vector2, TerrainChunk>();
- List<TerrainChunk> terrainChunksVisibleLastUpdate = new List<TerrainChunk>();
- private void Start()
- {
- mapGenerator = FindFirstObjectByType<MapGenerator>();
- chunkSize = MapGenerator.mapChunkSize - 1;
- chunksVisibleInViewDst = Mathf.RoundToInt(maxViewDist / chunkSize);
- }
- private void Update()
- {
- viewerPosition = new Vector2(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 Vector2(currentChunkCoordX + xOffset, currentChunkCoordY + yOffset);
- if (terrainChunkDictionary.ContainsKey(viewedChunkCoord))
- {
- terrainChunkDictionary[viewedChunkCoord].UpdateTerrainChunk();
- if (terrainChunkDictionary[viewedChunkCoord].IsVisible())
- {
- terrainChunksVisibleLastUpdate.Add(terrainChunkDictionary[viewedChunkCoord]);
- }
- }
- else
- {
- terrainChunkDictionary.Add(viewedChunkCoord, new TerrainChunk(viewedChunkCoord, chunkSize, transform, mapMaterial));
- }
- }
- }
- }
- public class TerrainChunk
- {
- GameObject meshObject;
- Vector2 position;
- Bounds bounds;
- MapData mapData;
- MeshRenderer meshRenderer;
- MeshFilter meshFilter;
- public TerrainChunk(Vector2 coord, int size, Transform parent, Material material)
- {
- position = coord * size;
- bounds = new Bounds(position, Vector2.one * size);
- Vector3 positionV3 = new Vector3(position.x, 0, position.y);
- meshObject = new GameObject("Terrain Chunk");
- meshRenderer = meshObject.AddComponent<MeshRenderer>();
- meshFilter = meshObject.AddComponent<MeshFilter>();
- meshRenderer.material = material;
- meshObject.transform.position = positionV3;
- meshObject.transform.parent = parent;
- SetVisible(false);
- mapGenerator.RequestMapData(OnMapDataReceived);
- }
- void OnMapDataReceived(MapData mapData)
- {
- mapGenerator.RequestMeshData(mapData, OnMeshDataReceived);
- }
- void OnMeshDataReceived(MeshData meshData)
- {
- meshFilter.mesh = meshData.CreateMesh();
- }
- public void UpdateTerrainChunk()
- {
- float viewerDstFromNearestEdge = Mathf.Sqrt(bounds.SqrDistance(viewerPosition));
- bool visible = viewerDstFromNearestEdge <= maxViewDist;
- SetVisible(visible);
- }
- public void SetVisible(bool visible)
- {
- meshObject.SetActive(visible);
- }
- public bool IsVisible()
- {
- return meshObject.activeSelf;
- }
- }
- }
|