/// <summary> /// Responds to chunk collider callbacks. Updates the navmesh based on the new collider data. /// </summary> /// <param name="chunk"></param> private void OnTerrainChunkColliderChanged(TerrainChunk chunk, bool hasSetCollider) { if (hasSetCollider) { if (IsBuildingNavmesh) { StopCoroutine(BuildNavMeshAsync()); } StartCoroutine(BuildNavMeshAsync()); } }
/// <summary> /// Responds to chunk visibility callbacks. Adds the chunk to a list of visible terrainChunks. /// </summary> /// <param name="chunk"></param> /// <param name="isVisible"></param> private void OnTerrainChunkVisibilityChanged(TerrainChunk chunk, bool isVisible) { if (isVisible) { visibleTerrainChunks.Add(chunk); } else { visibleTerrainChunks.Remove(chunk); } }
/// <summary> /// Update all visible chunks, tries to find new chunks aswell. /// </summary> private void UpdateVisibleChunks() { // Update the current visible chunks HashSet <Vector2> alreadyUpdatedChunkCoords = new HashSet <Vector2>(); for (int i = visibleTerrainChunks.Count - 1; i >= 0; i--) { alreadyUpdatedChunkCoords.Add(visibleTerrainChunks[i].Coord); visibleTerrainChunks[i].UpdateTerrainChunk(); } for (int yOffset = -1; yOffset <= 1; yOffset++) { for (int xOffset = -1; xOffset <= 1; xOffset++) { // Find new chunks based on secondary viewer positions foreach (var secondaryViewer in secondaryViewers.Values) { if (secondaryViewer.Transform == null) { Debug.LogWarning("Viewer has no transform"); continue; } int secondaryViewerChunkCoordX = Mathf.RoundToInt(secondaryViewer.Position.x / meshWorldSize); int secondaryViewerChunkCoordY = Mathf.RoundToInt(secondaryViewer.Position.y / meshWorldSize); Vector2 viewedChunkCoord = new Vector2(secondaryViewerChunkCoordX + xOffset, secondaryViewerChunkCoordY + yOffset); if (!alreadyUpdatedChunkCoords.Contains(viewedChunkCoord)) { if (terrainChunkDictionary.ContainsKey(viewedChunkCoord)) { TerrainChunk terrainChunk = terrainChunkDictionary[viewedChunkCoord]; terrainChunk.Viewer = secondaryViewer; } else { TerrainChunk newChunk = new TerrainChunk(viewedChunkCoord, HeightMapSettings, BiomeMapSettings, ResourceMapSettings, MeshSettings, detailLevels, colliderLODIndex, transform, secondaryViewer, TerrainMeshMaterial); terrainChunkDictionary.Add(viewedChunkCoord, newChunk); newChunk.OnVisibilityChanged += OnTerrainChunkVisibilityChanged; newChunk.OnColliderChanged += OnTerrainChunkColliderChanged; newChunk.Load(); } } } } } // Find new chunks based on primary viewer position int primaryViewerChunkCoordX = Mathf.RoundToInt(primaryViewer.Position.x / meshWorldSize); int primaryViewerChunkCoordY = Mathf.RoundToInt(primaryViewer.Position.y / meshWorldSize); for (int yOffset = -chunksVisibleInViewDistance; yOffset <= chunksVisibleInViewDistance; yOffset++) { for (int xOffset = -chunksVisibleInViewDistance; xOffset <= chunksVisibleInViewDistance; xOffset++) { Vector2 viewedChunkCoord = new Vector2(primaryViewerChunkCoordX + xOffset, primaryViewerChunkCoordY + yOffset); if (!alreadyUpdatedChunkCoords.Contains(viewedChunkCoord)) { if (terrainChunkDictionary.ContainsKey(viewedChunkCoord)) { TerrainChunk terrainChunk = terrainChunkDictionary[viewedChunkCoord]; terrainChunk.Viewer = primaryViewer; terrainChunk.UpdateTerrainChunk(); } else { TerrainChunk newChunk = new TerrainChunk(viewedChunkCoord, HeightMapSettings, BiomeMapSettings, ResourceMapSettings, MeshSettings, detailLevels, colliderLODIndex, transform, primaryViewer, TerrainMeshMaterial); terrainChunkDictionary.Add(viewedChunkCoord, newChunk); newChunk.OnVisibilityChanged += OnTerrainChunkVisibilityChanged; newChunk.OnColliderChanged += OnTerrainChunkColliderChanged; newChunk.Load(); } } } } }
public static ObjectPoint[] CreateObjectPoints(int uniformSize, MeshSettings meshSettings, ResourceMapSettings resourceMapSettings, BiomeMap biomeMap, HeightMap heightMap, TerrainChunk terrainChunk) { string fileName = $"chunkInfo{terrainChunk.Coord.x}{terrainChunk.Coord.y}.dat"; // Try to load a save file if (File.Exists(SaveDataManager.WorldDataPath + fileName)) { return(ObjectMapLoader.LoadObjectMap(terrainChunk, SaveDataManager.WorldDataPath).ObjectPoints); } else { //ResourceMap resourceMap = ResourceMapGenerator.GenerateResourceMap(uniformSize, resourceMapSettings, terrainChunk.SampleCenter); ResourceMap resourceMap = ResourceMapGenerator.GenerateResourceMap(uniformSize, resourceMapSettings, terrainChunk.SampleCenter, biomeMap, heightMap); List <ObjectPoint> tempObjectPoints = new List <ObjectPoint>(); // Resource points to object points foreach (var resourcePoint in resourceMap.resourcePoints) { int x = resourcePoint.x; int z = resourcePoint.z; HeightMapLayer layer = heightMap.GetLayer(x + 1, z + 1); // Don't spawn objects on water. if (layer.IsWater) { continue; } float height = heightMap.Values[x + 1, z + 1]; Vector3 position = new Vector3(terrainChunk.Bounds.center.x, 0f, terrainChunk.Bounds.center.y) + new Vector3((x - (uniformSize - 1) / 2f) * meshSettings.MeshScale, height, (z - (uniformSize - 1) / 2f) * -meshSettings.MeshScale); // Create a seeded System.Random for the rotation based on the position float a = position.x + position.y; float b = position.z + position.y; System.Random rand = new System.Random((int)(0.5 * (a + b) * (a + b + 1) + b)); Quaternion rotation = Quaternion.Euler(new Vector3(0f, rand.Next(0, 360), 0f)); int chunkPartSize = uniformSize / meshSettings.ChunkPartSizeRoot + 1; int coordX = Mathf.FloorToInt(x / chunkPartSize) - 1; int coordZ = Mathf.FloorToInt(z / chunkPartSize) - 1; Vector2 chunkPartCoords = terrainChunk.Coord * meshSettings.ChunkPartSizeRoot + new Vector2(coordX, -coordZ); tempObjectPoints.Add(new ObjectPoint(position, rotation, resourcePoint.biomeId, resourcePoint.worldResourcePrefabId, chunkPartCoords.x, chunkPartCoords.y)); } return(tempObjectPoints.ToArray()); } }
private static void FillChunkParts(int uniformSize, ref Dictionary <Vector2, TerrainChunkPart> chunkParts, MeshSettings meshSettings, ResourceMapSettings resourceMapSettings, BiomeMap biomeMap, HeightMap heightMap, TerrainChunk terrainChunk) { ObjectPoint[] objectPoints = CreateObjectPoints(uniformSize, meshSettings, resourceMapSettings, biomeMap, heightMap, terrainChunk); // Fill chunk parts for (int i = 0; i < objectPoints.Length; i++) { Vector2 chunkPartCoords = new Vector2(objectPoints[i].chunkPartCoordX, objectPoints[i].chunkPartCoordZ); TerrainChunkPart terrainChunkPart = chunkParts[chunkPartCoords]; terrainChunkPart.AddObjectPoint(objectPoints[i]); } }
private static Dictionary <Vector2, TerrainChunkPart> CreateChunkParts(int uniformSize, MeshSettings meshSettings, TerrainChunk terrainChunk) { Dictionary <Vector2, TerrainChunkPart> chunkParts = new Dictionary <Vector2, TerrainChunkPart>(); int chunkRangeHalf = Mathf.FloorToInt(meshSettings.ChunkPartSizeRoot / 2f); // ONLY WORKS FOR UNEVEN NUMBERS AT THE MOMENT for (int x = -chunkRangeHalf; x <= chunkRangeHalf; x++) { for (int z = -chunkRangeHalf; z <= chunkRangeHalf; z++) { Vector2 chunkPartCoord = terrainChunk.Coord * meshSettings.ChunkPartSizeRoot + new Vector2(x, z); Vector3 partWorldPosition = new Vector3(terrainChunk.Bounds.size.x / meshSettings.ChunkPartSizeRoot * chunkPartCoord.x, 0f, terrainChunk.Bounds.size.y / meshSettings.ChunkPartSizeRoot * chunkPartCoord.y); chunkParts.Add(chunkPartCoord, new TerrainChunkPart(chunkPartCoord, partWorldPosition, terrainChunk)); } } return(chunkParts); }
/// <summary> /// Generates a <see cref="DataMap"/> that consists of a heightmap, biomeMap and resourceMap based on a single size. Divides the resourceMap in <see cref="DataMap.ChunkParts"/> based on <see cref="MeshSettings.ChunkPartSizeRoot"/> /// </summary> /// <param name="terrainChunk">The terrain chunk that requested the DataMap.</param> /// <returns></returns> public static DataMap GenerateDataMap(MeshSettings meshSettings, HeightMapSettings heightMapSettings, BiomeMapSettings biomeMapSettings, ResourceMapSettings resourceMapSettings, TerrainChunk terrainChunk) { int size = meshSettings.NumVertsPerLine; int uniformSize = size - 2; // Generate data maps HeightMap heightMap = HeightMapGenerator.GenerateHeightMap(size, heightMapSettings, terrainChunk.SampleCenter); BiomeMap biomeMap = BiomeMapGenerator.GenerateBiomeMap(uniformSize, biomeMapSettings, terrainChunk.SampleCenter); // Create chunk parts Dictionary <Vector2, TerrainChunkPart> chunkParts = CreateChunkParts(uniformSize, meshSettings, terrainChunk); FillChunkParts(uniformSize, ref chunkParts, meshSettings, resourceMapSettings, biomeMap, heightMap, terrainChunk); return(new DataMap(uniformSize, heightMap, biomeMap, chunkParts)); }
public TerrainChunkPart(Vector2 coord, Vector3 worldPosition, TerrainChunk terrainChunk) { this.Coord = coord; this.WorldPosition = worldPosition; this.terrainChunk = terrainChunk; }