From a576c4a6edc69f703422ab289ee46b05011b9275 Mon Sep 17 00:00:00 2001 From: miepzerino <o.skotnik@gmail.com> Date: Sun, 06 Apr 2025 17:46:38 +0000 Subject: [PATCH] #48 added cache to map savefile --- Assets/Scripts/GenerateTileMap.cs | 202 ++++++++++++++++++++++++++++++++++++------------- 1 files changed, 147 insertions(+), 55 deletions(-) diff --git a/Assets/Scripts/GenerateTileMap.cs b/Assets/Scripts/GenerateTileMap.cs index 4bf8585..8870c8e 100644 --- a/Assets/Scripts/GenerateTileMap.cs +++ b/Assets/Scripts/GenerateTileMap.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; using Unity.Collections; using Unity.Jobs; using Unity.VisualScripting; @@ -10,9 +11,9 @@ public class GenerateTileMap : MonoBehaviour { public int? seed; - public static int maxWidth = 256; + public static int maxWidth = 255; public static int maxDepth = 384; - public static int groundDepth = 256; + public static int groundDepth = 255; private float scale; private float offsetX; private float offsetY; @@ -61,20 +62,32 @@ //Debug.Log($"Current Chunk: {currentChunk}"); if (currentChunk != lastLoadedChunk) { - StartCoroutine(UpdateLoadedChunks(currentChunk)); + StartCoroutine(UpdateLoadedChunks(currentChunk, gameManager.destroyedTiles)); lastLoadedChunk = currentChunk; // Check if we need to clear the cache ClearDistantChunks(currentChunk); } } - - // When checking if a tile is destroyed, use GameManager's list - private bool IsTileDestroyed(Vector3Int tilePos) + public Dictionary<Vector2Int, TileBase[]> GetSaveData() { - return gameManager.destroyedTiles.Contains(tilePos); + return chunkCache; } - private IEnumerator UpdateLoadedChunks(Vector2Int currentChunk) + public void LoadChunkDataFromSave(List<SerializedChunkData> serializedChunks) + { + chunkCache.Clear(); + foreach (var chunk in serializedChunks) + { + TileBase[] tiles = chunk.tileNames.Select(name => + name == "null" ? null : + name == forestRuleTile.name ? forestRuleTile : + forestRuleTile.siblings.FirstOrDefault(s => s.name == name) + ).ToArray(); + + chunkCache[chunk.position] = tiles; + } + } + private IEnumerator UpdateLoadedChunks(Vector2Int currentChunk, List<Vector3Int> destroyedTiles) { // Unload distant chunks List<Vector2Int> chunksToUnload = new List<Vector2Int>(); @@ -93,21 +106,13 @@ } // Load new chunks - yield return LoadChunksAroundPosition(currentChunk, new List<Vector3Int>()); + yield return LoadChunksAroundPosition(currentChunk, destroyedTiles); } private void UnloadChunk(Vector2Int chunk) { - int startX = chunk.x * CHUNK_SIZE; - int startY = (chunk.y * CHUNK_SIZE)-1; - - for (int x = startX; x < startX + CHUNK_SIZE; x++) - { - for (int y = startY; y > startY - CHUNK_SIZE; y--) - { - tilemap.SetTile(new Vector3Int(x, y), null); - } - } + var emptyTiles = new TileBase[CHUNK_SIZE * CHUNK_SIZE]; + BatchSetTiles(chunk, emptyTiles); } private void LoadGenerateablesFromResources() { @@ -192,7 +197,7 @@ finishedCallback(); } - private Vector2Int GetChunkPosition(Vector3 worldPosition) + public Vector2Int GetChunkPosition(Vector3 worldPosition) { // Adjust for tilemap offset float adjustedX = worldPosition.x - transform.position.x; @@ -202,6 +207,23 @@ Mathf.FloorToInt(adjustedX / CHUNK_SIZE), Mathf.FloorToInt(adjustedY / CHUNK_SIZE) ); + } + public void UpdateChunkCache(Vector3Int cellCoord, Vector3 cellWorldPosition) + { + // Update chunk cache + Vector2Int chunkPos = GetChunkPosition(cellWorldPosition); + if (chunkCache.TryGetValue(chunkPos, out TileBase[] cachedTiles)) + { + int localX = cellCoord.x - (chunkPos.x * GenerateTileMap.CHUNK_SIZE); + int localY = (chunkPos.y * GenerateTileMap.CHUNK_SIZE) - cellCoord.y - 1; + int index = localY * GenerateTileMap.CHUNK_SIZE + localX; + + if (index >= 0 && index < cachedTiles.Length) + { + cachedTiles[index] = null; + chunkCache[chunkPos] = cachedTiles; + } + } } private IEnumerator LoadChunksAroundPosition(Vector2Int centerChunk, List<Vector3Int> destroyedTiles) { @@ -235,19 +257,40 @@ if (chunkCache.TryGetValue(chunk, out TileBase[] cachedTiles)) { - for (int i = 0; i < cachedTiles.Length; i++) - { - int x = startX + (i % CHUNK_SIZE); - int y = startY - (i / CHUNK_SIZE); - Vector3Int tilePos = new Vector3Int(x, y); + //for (int i = 0; i < cachedTiles.Length; i++) + //{ + // int x = startX + (i % CHUNK_SIZE); + // int y = startY - (i / CHUNK_SIZE); + // Vector3Int tilePos = new Vector3Int(x, y); - if (!IsTileDestroyed(tilePos)) - { - tilemap.SetTile(tilePos, cachedTiles[i]); - } - } + // if (!IsTileDestroyed(tilePos)) + // { + // tilemap.SetTile(tilePos, cachedTiles[i]); + // } + //} + BatchSetTiles(chunk, cachedTiles, gameManager.destroyedTiles); } yield return null; + } + private void BatchSetTiles(Vector2Int chunk, TileBase[] tiles, List<Vector3Int> destroyedTiles = null) + { + int startX = chunk.x * CHUNK_SIZE; + int startY = (chunk.y * CHUNK_SIZE) - 1; + + var positions = new Vector3Int[CHUNK_SIZE * CHUNK_SIZE]; + var tileArray = new TileBase[CHUNK_SIZE * CHUNK_SIZE]; + + for (int i = 0; i < tiles.Length; i++) + { + int x = startX + (i % CHUNK_SIZE); + int y = startY - (i / CHUNK_SIZE); + Vector3Int pos = new Vector3Int(x, y); + + positions[i] = pos; + tileArray[i] = destroyedTiles != null && destroyedTiles.Contains(pos) ? null : tiles[i]; + } + + tilemap.SetTiles(positions, tileArray); } private void ClearDistantChunks(Vector2Int currentChunk) { @@ -324,29 +367,36 @@ // Apply the results groundJobHandle.Complete(); TileBase[] newChunkTiles = new TileBase[CHUNK_SIZE * CHUNK_SIZE]; + //for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE; i++) + //{ + // if (groundJob.groundTiles[i]) + // { + // int x = startX + (i % CHUNK_SIZE); + // int y = startY - (i / CHUNK_SIZE); + // Vector3Int tilePos = new Vector3Int(x, y); + + // if (!IsTileDestroyed(tilePos)) + // { + // tilemap.SetTile(tilePos, forestRuleTile); + // newChunkTiles[i] = forestRuleTile; + // } + // else + // { + // newChunkTiles[i] = null; + // } + // } + // else + // { + // newChunkTiles[i] = null; + // } + //} for (int i = 0; i < CHUNK_SIZE * CHUNK_SIZE; i++) { - if (groundJob.groundTiles[i]) - { - int x = startX + (i % CHUNK_SIZE); - int y = startY - (i / CHUNK_SIZE); - Vector3Int tilePos = new Vector3Int(x, y); - - if (!IsTileDestroyed(tilePos)) - { - tilemap.SetTile(tilePos, forestRuleTile); - newChunkTiles[i] = forestRuleTile; - } - else - { - newChunkTiles[i] = null; - } - } - else - { - newChunkTiles[i] = null; - } + newChunkTiles[i] = groundJob.groundTiles[i] ? forestRuleTile : null; } + + // Batch update tiles + BatchSetTiles(chunk, newChunkTiles, destroyedTiles); // Save the generated chunk to the cache chunkCache[chunk] = newChunkTiles; @@ -372,6 +422,8 @@ { int startX = chunk.x * CHUNK_SIZE; int startY = chunk.y * CHUNK_SIZE; + // Get the cached tiles for this chunk + TileBase[] cachedTiles = chunkCache[chunk]; foreach (Generateable generateable in generateables) { @@ -409,6 +461,14 @@ if (clusterSize >= generateable.minClusterSize) { tilemap.SetTile(tileSpawnCoord, generateable.tile); + // Update cache + int localX = x - startX; + int localY = startY - y - 1; + int index = localY * CHUNK_SIZE + localX; + if (index >= 0 && index < cachedTiles.Length) + { + cachedTiles[index] = generateable.tile; + } } } } @@ -422,25 +482,57 @@ } } } + // Update the cache with the modified tiles + chunkCache[chunk] = cachedTiles; } private IEnumerator GenerateBorders() { - // Vertical borders (going up from underground to sky) + // Vertical borders for (int x = 0; x <= maxWidth; x += maxWidth) { for (int y = -groundDepth; y <= maxDepth - groundDepth; y++) { - tilemap.SetTile(new Vector3Int(x, y), borderTile); + Vector3Int borderPos = new Vector3Int(x, y); + tilemap.SetTile(borderPos, borderTile); + + // Update cache for affected chunk + Vector2Int chunkPos = GetChunkPosition(new Vector3(x + transform.position.x, y + transform.position.y)); + if (chunkCache.TryGetValue(chunkPos, out TileBase[] cachedTiles)) + { + int localX = x - (chunkPos.x * CHUNK_SIZE); + int localY = chunkPos.y * CHUNK_SIZE - y - 1; + int index = localY * CHUNK_SIZE + localX; + if (index >= 0 && index < cachedTiles.Length) + { + cachedTiles[index] = borderTile; + chunkCache[chunkPos] = cachedTiles; + } + } } } yield return null; - // Horizontal borders (at bottom and sky level) + // Horizontal borders for (int y = -groundDepth; y <= maxDepth - groundDepth; y += maxDepth) { - for (int x = 1; x <= maxWidth; x++) + for (int x = 1; x < maxWidth; x++) { - tilemap.SetTile(new Vector3Int(x, y), borderTile); + Vector3Int borderPos = new Vector3Int(x, y); + tilemap.SetTile(borderPos, borderTile); + + // Update cache for affected chunk + Vector2Int chunkPos = GetChunkPosition(new Vector3(x + transform.position.x, y + transform.position.y)); + if (chunkCache.TryGetValue(chunkPos, out TileBase[] cachedTiles)) + { + int localX = x - (chunkPos.x * CHUNK_SIZE); + int localY = chunkPos.y * CHUNK_SIZE - y - 1; + int index = localY * CHUNK_SIZE + localX; + if (index >= 0 && index < cachedTiles.Length) + { + cachedTiles[index] = borderTile; + chunkCache[chunkPos] = cachedTiles; + } + } } } yield return null; -- Gitblit v1.9.3