miepzerino
2025-04-06 1ad7266ade6e7db1976436d4cd322dc72c20d4bb
Assets/Scripts/GenerateTileMap.cs
@@ -3,6 +3,7 @@
using System.Collections.Generic;
using Unity.Collections;
using Unity.Jobs;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Tilemaps;
@@ -23,8 +24,11 @@
    public const int CHUNK_SIZE = 16; // Size of each chunk
    public int LOAD_DISTANCE = 2; // Number of chunks to load around player
    private const int CACHE_CLEAR_DISTANCE = 8; // Distance in chunks before clearing cache (should be > LOAD_DISTANCE)
    private Vector2Int lastCacheClearPosition; // Track position where cache was last cleared
    private Dictionary<Vector2Int, bool> loadedChunks = new Dictionary<Vector2Int, bool>();
    private Dictionary<Vector2Int, TileBase[]> chunkCache = new Dictionary<Vector2Int, TileBase[]>();
    private Transform playerTransform; // Reference to player/camera
    private Vector2Int lastLoadedChunk;
    private GameManager gameManager;
@@ -59,6 +63,8 @@
        {
            StartCoroutine(UpdateLoadedChunks(currentChunk));
            lastLoadedChunk = currentChunk;
            // Check if we need to clear the cache
            ClearDistantChunks(currentChunk);
        }
    }
@@ -206,16 +212,93 @@
                Vector2Int chunkPos = new Vector2Int(centerChunk.x + x, centerChunk.y + y);
                if (!loadedChunks.ContainsKey(chunkPos))
                {
                    yield return GenerateChunk(chunkPos, destroyedTiles);
                    if (chunkCache.ContainsKey(chunkPos))
                    {
                        // Load the chunk from the cache
                        yield return LoadChunkFromCache(chunkPos);
                    }
                    else
                    {
                        // Generate the chunk
                        yield return GenerateChunk(chunkPos, destroyedTiles);
                    }
                    loadedChunks[chunkPos] = true;
                }
            }
        }
    }
    private IEnumerator LoadChunkFromCache(Vector2Int chunk)
    {
        int startX = chunk.x * CHUNK_SIZE;
        int startY = (chunk.y * CHUNK_SIZE) - 1;
        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);
                if (!IsTileDestroyed(tilePos))
                {
                    tilemap.SetTile(tilePos, cachedTiles[i]);
                }
            }
        }
        yield return null;
    }
    private void ClearDistantChunks(Vector2Int currentChunk)
    {
        // If this is the first time, initialize the last clear position
        if (lastCacheClearPosition == default)
        {
            lastCacheClearPosition = currentChunk;
            return;
        }
        // Calculate distance moved since last cache clear
        int distanceMoved = Mathf.Max(
            Mathf.Abs(currentChunk.x - lastCacheClearPosition.x),
            Mathf.Abs(currentChunk.y - lastCacheClearPosition.y)
        );
        // If we've moved far enough, clear distant chunks from cache
        if (distanceMoved >= CACHE_CLEAR_DISTANCE)
        {
            List<Vector2Int> chunksToRemove = new List<Vector2Int>();
            foreach (var chunk in chunkCache.Keys)
            {
                int distanceToPlayer = Mathf.Max(
                    Mathf.Abs(chunk.x - currentChunk.x),
                    Mathf.Abs(chunk.y - currentChunk.y)
                );
                // Remove chunks that are far from current position
                if (distanceToPlayer > LOAD_DISTANCE * 2)
                {
                    chunksToRemove.Add(chunk);
                }
            }
            // Remove the distant chunks from cache
            foreach (var chunk in chunksToRemove)
            {
                chunkCache.Remove(chunk);
            }
            lastCacheClearPosition = currentChunk;
            Debug.Log($"Cleared {chunksToRemove.Count} chunks from cache. Current cache size: {chunkCache.Count}");
        }
    }
    private IEnumerator GenerateChunk(Vector2Int chunk, List<Vector3Int> destroyedTiles)
    {
        int startX = chunk.x * CHUNK_SIZE;
        int startY = (chunk.y * CHUNK_SIZE) - 1;
        // Check if the chunk is already in the cache
        LoadChunkFromCache(chunk);
        // Create job data
        var groundJob = new GenerateGroundJob
@@ -240,6 +323,7 @@
        // 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])
@@ -251,9 +335,21 @@
                if (!IsTileDestroyed(tilePos))
                {
                    tilemap.SetTile(tilePos, forestRuleTile);
                    newChunkTiles[i] = forestRuleTile;
                }
                else
                {
                    newChunkTiles[i] = null;
                }
            }
            else
            {
                newChunkTiles[i] = null;
            }
        }
        // Save the generated chunk to the cache
        chunkCache[chunk] = newChunkTiles;
        // Clean up native array
        groundJob.groundTiles.Dispose();
@@ -301,6 +397,7 @@
                    {
                        float xPerlin = ((float)x / maxWidth) * (float)generateable.clusterWeight + offsetX;
                        float yPerlin = ((float)Mathf.Abs(y) / maxDepth) * (float)generateable.clusterWeight + offsetY;
                        float perlinNoise = Mathf.PerlinNoise(xPerlin, yPerlin);
                        if (perlinNoise <= (1f / (float)generateable.weight))
@@ -394,6 +491,7 @@
        {
            perlinNoiseCache.Dispose();
        }
        chunkCache.Clear();
    }
#if UNITY_EDITOR
    private void OnDrawGizmos()