/// <summary> /// Updates tiles that are surrounding the tracked GameObject /// asynchronously /// </summary> public IEnumerator UpdateTiles() { List <Vector2> nearbyPositions = GetTilePositionsFromRadius(); List <Vector2> newPositions = Cache.GetNewTilePositions(nearbyPositions); //Remove old positions for (int i = 0; i < Cache.ActiveTiles.Count; i++) { bool found = false; foreach (Vector2 nearby in nearbyPositions) { if (Cache.ActiveTiles[i].Position == nearby) //Position found, ignore { found = true; break; } } if (!found) { Cache.CacheTile(Cache.ActiveTiles[i]); Cache.ActiveTiles.RemoveAt(i); i--; } } //Add new positions foreach (Vector2 pos in newPositions) { TerrainTile cached = Cache.GetCachedTileAtPosition(pos); //Attempt to pull from cache, generate if not available if (cached != null) { Cache.AddActiveTile(cached); } else { yield return(AddTileAsync(pos)); } } }
/// <summary> /// Updates tiles that are surrounding the tracked GameObject /// asynchronously. When calling this method using /// <see cref="MonoBehaviour.StartCoroutine(IEnumerator)"/>, /// tiles are generated once per frame /// </summary> public IEnumerator UpdateTiles() { List <GridPosition> nearbyPositions = GetTilePositionsFromRadius(); List <GridPosition> newPositions = Cache.GetNewTilePositions(nearbyPositions); List <Tile> toRegenerate = new List <Tile>(); RemoveOldPositions(ref nearbyPositions, ref toRegenerate); //Add new positions _queuedTiles = newPositions.Count + toRegenerate.Count; foreach (GridPosition pos in newPositions) { if (_isGenerating && Application.isPlaying) //Wait and generate one tile per frame { yield return(null); } Tile cached = Cache.GetCachedTileAtPosition(pos); //Attempt to pull from cache, generate if not available if (cached != null) { if (cached.IsHeightmapLodValid()) //Cached tile is valid, use it { AddTile(cached); _queuedTiles--; continue; } TerraConfig.Log("Cached tile " + cached + " has heightmap res=" + cached.MeshManager.HeightmapResolution + ". requested res=" + cached.GetLodLevel().Resolution + ". Regenerating."); toRegenerate.Add(cached); Cache.AddActiveTile(cached); continue; } _isGenerating = true; CreateTileAt(pos, tile => { _queuedTiles--; if (_queuedTiles == 0) { UpdateNeighbors(newPositions.ToArray(), false); } _isGenerating = false; }); } //Regenerate tiles with outdated heightmaps for (int i = 0; i < toRegenerate.Count; i++) { Tile t = toRegenerate[i]; TerraConfig.Log("Active tile " + t + " has heightmap res=" + t.MeshManager.HeightmapResolution + ". requested res=" + t.GetLodLevel().Resolution + ". Regenerating."); //Generate one tile per frame if (Application.isPlaying) { yield return(null); } if (Application.isPlaying) { Config.StartCoroutine(t.UpdateHeightmapAsync(() => { UpdateNeighbors(new[] { t.GridPosition }, false); _queuedTiles--; }, RemapMin, RemapMax)); } else { t.UpdateHeightmap(RemapMin, RemapMax); } } //If tiles were updated synchronously, notify queue completion if (newPositions.Count > 0 && _queuedTiles == 0) { UpdateNeighbors(newPositions.ToArray(), false); } }
/// <summary> /// Updates tiles that are surrounding the tracked GameObject /// asynchronously. When calling this method using /// <see cref="MonoBehaviour.StartCoroutine(System.Collections.IEnumerator)"/>, /// tiles are generated once per frame /// </summary> public IEnumerator UpdateTiles() { List <GridPosition> nearbyPositions = GetTilePositionsFromRadius(); List <GridPosition> newPositions = Cache.GetNewTilePositions(nearbyPositions); List <Tile> needRegenerating = new List <Tile>(); //Remove old positions for (int i = 0; i < Cache.ActiveTiles.Count; i++) { bool found = false; foreach (GridPosition nearby in nearbyPositions) { Tile t = Cache.ActiveTiles[i]; if (t.GridPosition == nearby) //Position found in ActiveTiles { if (t.IsHeightmapLodValid()) //Correct heightmap, ignore { found = true; break; } //Invalid heightmap, mark for regeneration found = true; needRegenerating.Add(t); } } if (!found) { Cache.CacheTile(Cache.ActiveTiles[i]); Cache.ActiveTiles.RemoveAt(i); i--; } } //Add new positions _queuedTiles = newPositions.Count + needRegenerating.Count; foreach (GridPosition pos in newPositions) { Tile cached = Cache.GetCachedTileAtPosition(pos); //Attempt to pull from cache, generate if not available if (cached != null) { if (cached.IsHeightmapLodValid()) //Cached tile is valid, use it { AddTile(cached); _queuedTiles--; continue; } //Cached tile has too low lod, mark for regeneration Debug.Log("Cached tile " + cached + " has heightmap res=" + cached.MeshManager.MeshResolution + ". requested res=" + cached.LodLevel.MeshResolution + ". Regenerating."); //Cache.RemoveCachedTile(cached); needRegenerating.Add(cached); Cache.AddActiveTile(cached); continue; } //Generate one tile per frame if (Application.isPlaying) { yield return(null); } _isGeneratingTile = true; AddTileAt(pos, tile => { _queuedTiles--; _isGeneratingTile = false; if (_queuedTiles == 0) { _queueCompletedAction(newPositions.ToArray()); } }); } //Regenerate tiles with outdated positions for (int i = 0; i < needRegenerating.Count; i++) { Tile t = needRegenerating[i]; Debug.Log("Active tile " + t + " has heightmap res=" + t.MeshManager.MeshResolution + ". requested res=" + t.LodLevel.MeshResolution + ". Regenerating."); //Generate one tile per frame if (Application.isPlaying) { yield return(null); } _isGeneratingTile = true; AddTileAt(t.GridPosition, tile => { _queuedTiles--; _isGeneratingTile = false; //Remove low res tile Cache.RemoveActiveTile(t); Cache.RemoveCachedTile(t); if (_queuedTiles == 0) { _queueCompletedAction(newPositions.ToArray()); } }); } //If tiles were updated synchronously, notify queue completion if (newPositions.Count > 0 && _queuedTiles == 0) { _queueCompletedAction(newPositions.ToArray()); } }