/
EndlessTerrain.cs
108 lines (81 loc) · 3.18 KB
/
EndlessTerrain.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class EndlessTerrain : MonoBehaviour {
public const float maxViewDst = 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>();
void Start() {
mapGenerator = FindObjectOfType<MapGenerator> ();
chunkSize = MapGenerator.mapChunkSize - 1;
chunksVisibleInViewDst = Mathf.RoundToInt(maxViewDst / chunkSize);
}
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;
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 <= maxViewDst;
SetVisible (visible);
}
public void SetVisible(bool visible) {
meshObject.SetActive (visible);
}
public bool IsVisible() {
return meshObject.activeSelf;
}
}
}