Forum begins after the advertisement:


[General] Map Generation and teleporting player

Home Forums Video Game Tutorial Series Creating a Rogue-like Shoot-em Up in Unity [General] Map Generation and teleporting player

Viewing 20 posts - 21 through 40 (of 47 total)
  • Author
    Posts
  • #18455
    Grim Rubbish
    Level 24
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    Can you be more specific about the logic behind the “loadedChunks” and how to handle them with the functions? I don’t want to use the function “UnloadNearbyChunks(Vector2 position)” with “Destroy(chunk);” because it causes all props to drop their loot from their attached “DropRateManager.cs” what can cause other problems.

    private HashSet loadedChunks = new HashSet();
    
        public void LoadChunk(Vector2 position)
        {
            if (!loadedChunks.Contains(position))
            {
                // Instantiate your chunk here
                loadedChunks.Add(position);
            }
        }
    
        public void UnloadChunk(Vector2 position)
        {
            // Remove the chunk and any related logic here
            loadedChunks.Remove(position);
        }

    Maybe the script can automatically check if there’s already another chunk at the position the new one should be spawned. There should only spawn a new chunk if the position is not already occupied by another chunk that’s not active and just has to be activated.

    #18456
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Here’s an improved approach to chunk management:

    private HashSet loadedChunks = new HashSet();
    private Dictionary chunkDictionary = new Dictionary();
    
    public void LoadChunk(Vector2 position)
    {
        if (!loadedChunks.Contains(position))
        {
            // Check if a chunk exists at this position but is inactive
            if (chunkDictionary.TryGetValue(position, out GameObject existingChunk))
            {
                // Reactivate the existing chunk
                existingChunk.SetActive(true);
            }
            else
            {
                // Instantiate a new chunk if no chunk exists
                GameObject newChunk = Instantiate(chunkPrefab, position, Quaternion.identity);
                chunkDictionary[position] = newChunk;
            }
    
            loadedChunks.Add(position);
        }
    }
    
    public void UnloadChunk(Vector2 position)
    {
        if (loadedChunks.Contains(position) && 
            chunkDictionary.TryGetValue(position, out GameObject chunk))
        {
            // Deactivate instead of destroying
            chunk.SetActive(false);
            loadedChunks.Remove(position);
        }
    }

    This approach:

    1. Uses a dictionary to track chunk references
    2. Reactivates existing chunks instead of destroying them
    3. Prevents respawning chunks at occupied positions
    4. Preserves props and loot by deactivating instead of destroying

    Would you like me to elaborate on any part of this implementation?

    #18457
    Grim Rubbish
    Level 24
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    Can you please post the complete “MapController.cs” with all needed functions included?

    #18458
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    I noticed that the reference information provided earlier was incomplete and did not contain a full MapController implementation. Without the complete context, I cannot confidently generate a full script.

    Could you provide:

    1. The full existing MapController.cs code
    2. Specific requirements for chunk management
    3. Details about how chunks should be spawned and managed
    4. Any existing methods or logic you want to preserve

    This will help me create a comprehensive and accurate MapController script tailored to your specific needs.

    #18459
    Grim Rubbish
    Level 24
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    Here is the”MapController.cs”. Can you please provide the full Script with included chunk management mentioned above for me?

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class MapController : MonoBehaviour
    {
        public List<GameObject> terrainChunks;
        public GameObject player;
        public float checkerRadius;
        public LayerMask terrainMask;
        public GameObject currentChunk;
        Vector3 playerLastPosition;
    
        [Header("Optimization")]
        public List<GameObject> spawnedChunks;
        GameObject latestChunk;
        public float maxOpDist; //Must be greater than the length and width of the tilemap
        float opDist;
        float optimizerCooldown;
        public float optimizerCooldownDur;
    
        void Start()
        {
            playerLastPosition = player.transform.position;
        }
    
        void Update()
        {
            ChunkChecker();
            ChunkOptimzer();
        }
    
        void ChunkChecker()
        {
            if (!currentChunk)
            {
                return;
            }
    
            Vector3 moveDir = player.transform.position - playerLastPosition;
            playerLastPosition = player.transform.position;
    
            string directionName = GetDirectionName(moveDir);
    
    
            CheckAndSpawnChunk(directionName);
    
            // Check additional adjacent directions for diagonal chunks
            if (directionName.Contains("Up"))
            {
                CheckAndSpawnChunk("Up");
                CheckAndSpawnChunk("Left");
                CheckAndSpawnChunk("Right");
            }
            else if (directionName.Contains("Down"))
            {
                CheckAndSpawnChunk("Down");
                CheckAndSpawnChunk("Left");
                CheckAndSpawnChunk("Right");
            }
            else if (directionName.Contains("Right"))
            {
                CheckAndSpawnChunk("Right");
                CheckAndSpawnChunk("Down");
                CheckAndSpawnChunk("Up");
            }
            else if (directionName.Contains("Left"))
            {
                CheckAndSpawnChunk("Left");
                CheckAndSpawnChunk("Down");
                CheckAndSpawnChunk("Up");
            }
        }
        void CheckAndSpawnChunk(string direction)
        {
            if (!Physics2D.OverlapCircle(currentChunk.transform.Find(direction).position, checkerRadius, terrainMask))
            {
                SpawnChunk(currentChunk.transform.Find(direction).position);
            }
        }
    
        string GetDirectionName(Vector3 direction)
        {
            direction = direction.normalized;
    
            if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y))
            {
                // Moving horizontally more than vertically
                if (direction.y > 0.5f)
                {
                    // Also moving upwards
                    return direction.x > 0 ? "RightUp" : "LeftUp";
                }
                else if (direction.y < -0.5f)
                {
                    // Also moving downwards
                    return direction.x > 0 ? "RightDown" : "LeftDown";
                }
                else
                {
                    // Moving straight horizontally
                    return direction.x > 0 ? "Right" : "Left";
                }
            }
            else
            {
                // Moving vertically more than horizontally
                if (direction.x > 0.5f)
                {
                    // Also moving right
                    return direction.y > 0 ? "RightUp" : "RightDown";
                }
                else if (direction.x < -0.5f)
                {
                    // Also moving left
                    return direction.y > 0 ? "LeftUp" : "LeftDown";
                }
                else
                {
                    // Moving straight vertically
                    return direction.y > 0 ? "Up" : "Down";
                }
            }
        }
    
        void SpawnChunk(Vector3 spawnPosition)
        {
            int rand = Random.Range(0, terrainChunks.Count);
            latestChunk = Instantiate(terrainChunks[rand], spawnPosition, Quaternion.identity);
            spawnedChunks.Add(latestChunk);
        }
    
        void ChunkOptimzer()
        {
            optimizerCooldown -= Time.deltaTime;
    
            if (optimizerCooldown <= 0f)
            {
                optimizerCooldown = optimizerCooldownDur;   //Check every 1 second to save cost, change this value to lower to check more times
            }
            else
            {
                return;
            }
    
            foreach (GameObject chunk in spawnedChunks)
            {
                opDist = Vector3.Distance(player.transform.position, chunk.transform.position);
                if (opDist > maxOpDist)
                {
                    chunk.SetActive(false);
                }
                else
                {
                    chunk.SetActive(true);
                }
            }
        }
    }
    #18460
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Here’s an updated MapController.cs with improved chunk management:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class MapController : MonoBehaviour
    {
        public List terrainChunks;
        public GameObject player;
        public float checkerRadius;
        public LayerMask terrainMask;
        public GameObject currentChunk;
        Vector3 playerLastPosition;
    
        [Header("Optimization")]
        public List spawnedChunks;
        private Dictionary chunkDictionary = new Dictionary();
        private HashSet loadedChunks = new HashSet();
        GameObject latestChunk;
        public float maxOpDist; //Must be greater than the length and width of the tilemap
        float opDist;
        float optimizerCooldown;
        public float optimizerCooldownDur;
    
        void Start()
        {
            playerLastPosition = player.transform.position;
        }
    
        void Update()
        {
            ChunkChecker();
            ChunkOptimzer();
        }
    
        void ChunkChecker()
        {
            if (!currentChunk)
            {
                return;
            }
    
            Vector3 moveDir = player.transform.position - playerLastPosition;
            playerLastPosition = player.transform.position;
    
            string directionName = GetDirectionName(moveDir);
    
            CheckAndSpawnChunk(directionName);
    
            // Check additional adjacent directions for diagonal chunks
            if (directionName.Contains("Up"))
            {
                CheckAndSpawnChunk("Up");
                CheckAndSpawnChunk("Left");
                CheckAndSpawnChunk("Right");
            }
            else if (directionName.Contains("Down"))
            {
                CheckAndSpawnChunk("Down");
                CheckAndSpawnChunk("Left");
                CheckAndSpawnChunk("Right");
            }
            else if (directionName.Contains("Right"))
            {
                CheckAndSpawnChunk("Right");
                CheckAndSpawnChunk("Down");
                CheckAndSpawnChunk("Up");
            }
            else if (directionName.Contains("Left"))
            {
                CheckAndSpawnChunk("Left");
                CheckAndSpawnChunk("Down");
                CheckAndSpawnChunk("Up");
            }
        }
    
        void CheckAndSpawnChunk(string direction)
        {
            Vector3 spawnPosition = currentChunk.transform.Find(direction).position;
            Vector2 chunkPos = new Vector2(spawnPosition.x, spawnPosition.y);
    
            if (!Physics2D.OverlapCircle(spawnPosition, checkerRadius, terrainMask))
            {
                LoadChunk(chunkPos);
            }
        }
    
        void LoadChunk(Vector2 position)
        {
            if (!loadedChunks.Contains(position))
            {
                // Check if a chunk exists at this position but is inactive
                if (chunkDictionary.TryGetValue(position, out GameObject existingChunk))
                {
                    // Reactivate the existing chunk
                    existingChunk.SetActive(true);
                }
                else
                {
                    // Instantiate a new chunk if no chunk exists
                    int rand = Random.Range(0, terrainChunks.Count);
                    GameObject newChunk = Instantiate(terrainChunks[rand], position, Quaternion.identity);
                    chunkDictionary[position] = newChunk;
                    spawnedChunks.Add(newChunk);
                }
    
                loadedChunks.Add(position);
            }
        }
    
        void UnloadChunk(Vector2 position)
        {
            if (loadedChunks.Contains(position) && 
                chunkDictionary.TryGetValue(position, out GameObject chunk))
            {
                // Deactivate instead of destroying
                chunk.SetActive(false);
                loadedChunks.Remove(position);
            }
        }
    
        string GetDirectionName(Vector3 direction)
        {
            // Existing GetDirectionName method remains the same
            direction = direction.normalized;
    
            if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y))
            {
                // Moving horizontally more than vertically
                if (direction.y > 0.5f)
                {
                    // Also moving upwards
                    return direction.x > 0 ? "RightUp" : "LeftUp";
                }
                else if (direction.y  0 ? "RightDown" : "LeftDown";
                }
                else
                {
                    // Moving straight horizontally
                    return direction.x > 0 ? "Right" : "Left";
                }
            }
            else
            {
                // Moving vertically more than horizontally
                if (direction.x > 0.5f)
                {
                    // Also moving right
                    return direction.y > 0 ? "RightUp" : "RightDown";
                }
                else if (direction.x  0 ? "LeftUp" : "LeftDown";
                }
                else
                {
                    // Moving straight vertically
                    return direction.y > 0 ? "Up" : "Down";
                }
            }
        }
    
        void ChunkOptimzer()
        {
            optimizerCooldown -= Time.deltaTime;
    
            if (optimizerCooldown  maxOpDist)
                {
                    UnloadChunk(new Vector2(chunk.transform.position.x, chunk.transform.position.y));
                }
            }
        }
    }

    Key improvements:

    1. Added chunkDictionary to track chunk references
    2. Implemented LoadChunk method to reactivate or spawn new chunks
    3. Added UnloadChunk method to deactivate chunks instead of destroying
    4. Prevents respawning chunks at occupied positions
    5. Preserves props and loot by deactivating instead of destroying

    Would you like me to explain any part of the implementation?

    #18461
    Grim Rubbish
    Level 24
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    I try to find a (temporarily) solition an I will post the final “MapController.cs” and “ChunkTrigger.cs” here later.

    #18462
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    The provided scripts look like a solid implementation for chunk management in a procedural map generation system. The key improvements include:

    1. MapController.cs:
    • Added loadedChunks HashSet to track loaded chunk positions
    • Implemented LoadChunk() and UnloadChunk() methods
    • Added UnloadNearbyChunks() method to manage chunk destruction
    • Retained existing chunk spawning and optimization logic
    1. ChunkTrigger.cs:
    • Added OnTriggerEnter2D() to load chunks when player enters
    • Manages currentChunk reference in OnTriggerStay2D()
    • Handles chunk unloading in OnTriggerExit2D()

    The implementation looks clean and should provide a good foundation for dynamic map generation.

    Would you like me to elaborate on any specific aspect of the chunk management system?

    #18463
    Grim Rubbish
    Level 24
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    I think there is something missing again:

    private Dictionary chunkDictionary = new Dictionary();

    should be something like

    private Dictionary<Vector2, GameObject> chunkDictionary = new Dictionary<Vector2, GameObject>(); or not?

    #18464
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Yes, you are correct. The generic type specification is necessary to define the dictionary’s key and value types.

    private Dictionary chunkDictionary = new Dictionary();

    This declaration ensures that:

    • The key is a Vector2 (representing chunk position)
    • The value is a GameObject (the actual chunk object)
    • Type safety is maintained
    • The dictionary can be used to efficiently look up and manage chunks by their position

    Would you like me to show how this dictionary might be used in the context of the MapController script?

    #18465
    Grim Rubbish
    Level 24
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    Yes, show me please.

    #18466
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Here’s an example of how to integrate the chunkDictionary into the MapController.cs:

    public class MapController : MonoBehaviour
    {
        // Existing fields...
        private Dictionary chunkDictionary = new Dictionary();
    
        public void LoadChunk(Vector2 position)
        {
            if (!loadedChunks.Contains(position))
            {
                // Check if chunk already exists in dictionary
                if (chunkDictionary.TryGetValue(position, out GameObject existingChunk))
                {
                    // Reactivate existing chunk
                    existingChunk.SetActive(true);
                }
                else
                {
                    // Spawn new chunk
                    int rand = Random.Range(0, terrainChunks.Count);
                    GameObject newChunk = Instantiate(terrainChunks[rand], position, Quaternion.identity);
    
                    // Add to dictionary and spawned chunks list
                    chunkDictionary[position] = newChunk;
                    spawnedChunks.Add(newChunk);
                }
    
                loadedChunks.Add(position);
            }
        }
    
        public void UnloadChunk(Vector2 position)
        {
            if (chunkDictionary.TryGetValue(position, out GameObject chunk))
            {
                // Deactivate or destroy the chunk
                chunk.SetActive(false);
    
                // Remove from tracking
                loadedChunks.Remove(position);
                spawnedChunks.Remove(chunk);
            }
        }
    
        void ChunkOptimzer()
        {
            // Modify existing optimizer to use dictionary
            foreach (var kvp in chunkDictionary.ToList())
            {
                Vector2 chunkPosition = kvp.Key;
                GameObject chunk = kvp.Value;
    
                float opDist = Vector3.Distance(player.transform.position, chunk.transform.position);
                if (opDist > maxOpDist)
                {
                    UnloadChunk(chunkPosition);
                }
            }
        }
    }

    Key improvements:

    1. Uses chunkDictionary to efficiently track and retrieve chunks
    2. Prevents duplicate chunk spawning
    3. Provides easy lookup and management of chunks by position
    4. Integrates with existing chunk loading and unloading logic

    Would you like me to elaborate on any part of this implementation?

    #18467
    Grim Rubbish
    Level 24
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    Okay, and what must be changend in the “ChunkTrigger.cs” to make everything work?

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class ChunkTrigger : MonoBehaviour
    {
        MapController mc;
    
        public GameObject targetMap;
    
        void Start()
        {
            mc = FindObjectOfType<MapController>();
        }
        public void OnTriggerEnter2D(Collider2D other)
        {
            if (other.CompareTag("Player"))
            {
                Vector2 chunkPosition = new Vector2(transform.position.x, transform.position.y);
                mc.LoadChunk(chunkPosition);
            }
        }
    
        private void OnTriggerStay2D(Collider2D col)
        {
            if (col.CompareTag("Player"))
            {
                mc.currentChunk = targetMap;
            }
        }
    
        private void OnTriggerExit2D(Collider2D col)
        {
            if (col.CompareTag("Player"))
            { 
                if (mc.currentChunk == targetMap)
                {
                    Vector2 chunkPositionTest = new Vector2(transform.position.x, transform.position.y);
                    mc.UnloadChunk(chunkPositionTest); 
                    mc.currentChunk = null;    
                }
            }
        }
    }
    #18468
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    The current ChunkTrigger.cs looks mostly fine, but I recommend a few minor adjustments:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class ChunkTrigger : MonoBehaviour
    {
      MapController mc;
    
      public GameObject targetMap;
      private Vector2 chunkPosition;
    
      void Start()
      {
          mc = FindObjectOfType();
          // Calculate chunk position once during initialization
          chunkPosition = new Vector2(transform.position.x, transform.position.y);
      }
    
      public void OnTriggerEnter2D(Collider2D other)
      {
          if (other.CompareTag("Player"))
          {
              mc.LoadChunk(chunkPosition);
          }
      }
    
      private void OnTriggerStay2D(Collider2D col)
      {
          if (col.CompareTag("Player"))
          {
              mc.currentChunk = targetMap;
          }
      }
    
      private void OnTriggerExit2D(Collider2D col)
      {
          if (col.CompareTag("Player"))
          { 
              if (mc.currentChunk == targetMap)
              {
                  mc.UnloadChunk(chunkPosition); 
                  mc.currentChunk = null;    
              }
          }
      }
    }

    Key changes:

    1. Moved chunkPosition calculation to Start() method to avoid repeated calculations
    2. Used the pre-calculated chunkPosition in all methods
    3. Kept the core logic of loading/unloading chunks and managing currentChunk

    Would you like me to elaborate on any part of these changes?

    #18469
    Grim Rubbish
    Level 24
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    With the above examples, chunks won’t disappear anymore. Here are my latest “MapController.cs” and “ChunkTrigger.cs” scripts:

    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using UnityEditor.VersionControl;
    using UnityEngine;
    
    public class MapController : MonoBehaviour
    {
        public List<GameObject> terrainChunks;
        public GameObject player;
        public float checkerRadius;
        public LayerMask terrainMask;
        public GameObject currentChunk;
        Vector3 playerLastPosition;
    
        [Header("Optimization")]
        public List<GameObject> spawnedChunks;
        GameObject latestChunk;
        public float maxOpDist; //Must be greater than the length and width of the tilemap
        float opDist;
        float optimizerCooldown;
        public float optimizerCooldownDur;
        private HashSet<Vector2> loadedChunks = new HashSet<Vector2>();
        private Dictionary<Vector2, GameObject> chunkDictionary = new Dictionary<Vector2, GameObject>();
    
        void Start()
        {
            playerLastPosition = player.transform.position;
        }
    
        void Update()
        {
            ChunkChecker();
            ChunkOptimzer();
        }
    
        public void LoadChunk(Vector2 position)
        {
            if (!loadedChunks.Contains(position))
            {
                // Check if chunk already exists in dictionary
                if (chunkDictionary.TryGetValue(position, out GameObject existingChunk))
                {
                    // Reactivate existing chunk
                    existingChunk.SetActive(true);
                }
                else
                {
                    // Spawn new chunk
                    int rand = Random.Range(0, terrainChunks.Count);
                    GameObject newChunk = Instantiate(terrainChunks[rand], position, Quaternion.identity);
    
                    // Add to dictionary and spawned chunks list
                    chunkDictionary[position] = newChunk;
                    spawnedChunks.Add(newChunk);
                }
    
                loadedChunks.Add(position);
            }
        }
    
        public void UnloadChunk(Vector2 position)
        {
            if (chunkDictionary.TryGetValue(position, out GameObject chunk))
            {
                // Deactivate or destroy the chunk
                chunk.SetActive(false);
    
                // Remove from tracking
                loadedChunks.Remove(position);
                spawnedChunks.Remove(chunk);
            }
        }
    
        public void UnloadNearbyChunks(Vector2 position)
        {
            // Iterate through all currently spawned chunks
            foreach (GameObject chunk in spawnedChunks.ToList())
            {
                // Destroy chunks that are far from the new position
                if (Vector3.Distance(chunk.transform.position, position) > maxOpDist)
                {
                    spawnedChunks.Remove(chunk);
                    Destroy(chunk);
                }
            }
    
            // Reset the current chunk reference
            currentChunk = null;
        }
        void ChunkChecker()
        {
            if (!currentChunk)
            {
                return;
            }
    
            Vector3 moveDir = player.transform.position - playerLastPosition;
            playerLastPosition = player.transform.position;
    
            string directionName = GetDirectionName(moveDir);
    
    
            CheckAndSpawnChunk(directionName);
    
            // Check additional adjacent directions for diagonal chunks
            if (directionName.Contains("Up"))
            {
                CheckAndSpawnChunk("Up");
                CheckAndSpawnChunk("Left");
                CheckAndSpawnChunk("Right");
            }
            else if (directionName.Contains("Down"))
            {
                CheckAndSpawnChunk("Down");
                CheckAndSpawnChunk("Left");
                CheckAndSpawnChunk("Right");
            }
            else if (directionName.Contains("Right"))
            {
                CheckAndSpawnChunk("Right");
                CheckAndSpawnChunk("Down");
                CheckAndSpawnChunk("Up");
            }
            else if (directionName.Contains("Left"))
            {
                CheckAndSpawnChunk("Left");
                CheckAndSpawnChunk("Down");
                CheckAndSpawnChunk("Up");
            }
        }
        void CheckAndSpawnChunk(string direction)
        {
            if (!Physics2D.OverlapCircle(currentChunk.transform.Find(direction).position, checkerRadius, terrainMask))
            {
                SpawnChunk(currentChunk.transform.Find(direction).position);
            }
        }
    
        string GetDirectionName(Vector3 direction)
        {
            direction = direction.normalized;
    
            if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y))
            {
                // Moving horizontally more than vertically
                if (direction.y > 0.5f)
                {
                    // Also moving upwards
                    return direction.x > 0 ? "RightUp" : "LeftUp";
                }
                else if (direction.y < -0.5f)
                {
                    // Also moving downwards
                    return direction.x > 0 ? "RightDown" : "LeftDown";
                }
                else
                {
                    // Moving straight horizontally
                    return direction.x > 0 ? "Right" : "Left";
                }
            }
            else
            {
                // Moving vertically more than horizontally
                if (direction.x > 0.5f)
                {
                    // Also moving right
                    return direction.y > 0 ? "RightUp" : "RightDown";
                }
                else if (direction.x < -0.5f)
                {
                    // Also moving left
                    return direction.y > 0 ? "LeftUp" : "LeftDown";
                }
                else
                {
                    // Moving straight vertically
                    return direction.y > 0 ? "Up" : "Down";
                }
            }
        }
    
        void SpawnChunk(Vector3 spawnPosition)
        {
            int rand = Random.Range(0, terrainChunks.Count);
            latestChunk = Instantiate(terrainChunks[rand], spawnPosition, Quaternion.identity);
            spawnedChunks.Add(latestChunk);
        }
        void ChunkOptimzer()
        {
            // Modify existing optimizer to use dictionary
            foreach (var kvp in chunkDictionary.ToList())
            {
                Vector2 chunkPosition = kvp.Key;
                GameObject chunk = kvp.Value;
    
                float opDist = Vector3.Distance(player.transform.position, chunk.transform.position);
                if (opDist > maxOpDist)
                {
                    UnloadChunk(chunkPosition);
                }
            }
        }
    
        void ChunkOptimzerOld()
        {
            optimizerCooldown -= Time.deltaTime;
    
            if (optimizerCooldown <= 0f)
            {
                optimizerCooldown = optimizerCooldownDur;   //Check every 1 second to save cost, change this value to lower to check more times
            }
            else
            {
                return;
            }
    
            foreach (GameObject chunk in spawnedChunks)
            {
                opDist = Vector3.Distance(player.transform.position, chunk.transform.position);
                if (opDist > maxOpDist)
                {
                    chunk.SetActive(false);
                }
                else
                {
                    chunk.SetActive(true);
                }
            }
        }
    }
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class ChunkTrigger : MonoBehaviour
    {
        MapController mc;
    
        public GameObject targetMap;
        private Vector2 chunkPosition;
    
        void Start()
        {
            mc = FindObjectOfType<MapController>();
            // Calculate chunk position once during initialization
            chunkPosition = new Vector2(transform.position.x, transform.position.y);
        }
    
        public void OnTriggerEnter2D(Collider2D other)
        {
            if (other.CompareTag("Player"))
            {
                mc.LoadChunk(chunkPosition);
            }
        }
    
        private void OnTriggerStay2D(Collider2D col)
        {
            if (col.CompareTag("Player"))
            {
                mc.currentChunk = targetMap;
            }
        }
    
        private void OnTriggerExit2D(Collider2D col)
        {
            if (col.CompareTag("Player"))
            {
                if (mc.currentChunk == targetMap)
                {
                    mc.UnloadChunk(chunkPosition);
                    mc.currentChunk = null;
                }
            }
        }
    }
    #18470
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    The scripts look mostly good, but there are a few potential improvements to prevent chunks from disappearing:

    1. In MapController.cs, modify the UnloadChunk method to not remove the chunk from the dictionary:
    public void UnloadChunk(Vector2 position)
    {
        if (chunkDictionary.TryGetValue(position, out GameObject chunk))
        {
            // Deactivate the chunk instead of removing it completely
            chunk.SetActive(false);
    
            // Remove from loaded chunks, but keep in dictionary
            loadedChunks.Remove(position);
            spawnedChunks.Remove(chunk);
        }
    }
    1. Modify the LoadChunk method to reactivate inactive chunks:
    public void LoadChunk(Vector2 position)
    {
        if (!loadedChunks.Contains(position))
        {
            // Check if chunk already exists in dictionary
            if (chunkDictionary.TryGetValue(position, out GameObject existingChunk))
            {
                // Reactivate existing chunk
                existingChunk.SetActive(true);
            }
            else
            {
                // Spawn new chunk
                int rand = Random.Range(0, terrainChunks.Count);
                GameObject newChunk = Instantiate(terrainChunks[rand], position, Quaternion.identity);
    
                // Add to dictionary and spawned chunks list
                chunkDictionary[position] = newChunk;
                spawnedChunks.Add(newChunk);
            }
    
            loadedChunks.Add(position);
        }
    }
    1. In the ChunkOptimzer method, consider adding a cooldown to reduce performance overhead:
    private float optimizerCooldown;
    public float optimizerCooldownDuration = 1f;
    
    void ChunkOptimzer()
    {
        optimizerCooldown -= Time.deltaTime;
        if (optimizerCooldown > 0) return;
    
        optimizerCooldown = optimizerCooldownDuration;
    
        foreach (var kvp in chunkDictionary.ToList())
        {
            Vector2 chunkPosition = kvp.Key;
            GameObject chunk = kvp.Value;
    
            float opDist = Vector3.Distance(player.transform.position, chunk.transform.position);
            if (opDist > maxOpDist)
            {
                UnloadChunk(chunkPosition);
            }
        }
    }

    These changes should help prevent chunks from disappearing unexpectedly while maintaining efficient chunk management.

    Would you like me to elaborate on any of these suggestions?

    #18471
    Grim Rubbish
    Level 24
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    The problem is still not solved. With this configuration of those two scripts, chunks that should get deactivated just stay activated.

    #18472
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Could you provide more specific details about how the chunks are behaving?

    Specifically:

    1. Are the chunks staying active even when far from the player?
    2. Can you confirm the maxOpDist value is set correctly?
    3. Are you seeing any debug logs or error messages?
    4. Have you verified that the ChunkOptimzer() method is being called?

    A detailed description of the exact behavior will help me diagnose the issue more precisely.

    #18473
    Grim Rubbish
    Level 24
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::
    • The chunks staying active even when far from the player.
    • maxOpDist is set correcly.
    • I get any debug logs and no error messages.
    • ChunkOptimzer() is called.
    #18474
    Alp Apustaja
    Level 10
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Let’s modify the ChunkOptimzer() method to add more explicit deactivation logic:

    void ChunkOptimzer()
    {
        // Create a list to track chunks to unload
        List chunksToUnload = new List();
    
        // Iterate through all chunks in the dictionary
        foreach (var kvp in chunkDictionary)
        {
            Vector2 chunkPosition = kvp.Key;
            GameObject chunk = kvp.Value;
    
            // Calculate distance from player to chunk
            float distanceToPlayer = Vector3.Distance(player.transform.position, chunk.transform.position);
    
            // If chunk is too far, mark for unloading
            if (distanceToPlayer > maxOpDist)
            {
                // Explicitly deactivate the chunk
                chunk.SetActive(false);
                chunksToUnload.Add(chunkPosition);
            }
        }
    
        // Remove marked chunks from loaded chunks
        foreach (Vector2 position in chunksToUnload)
        {
            loadedChunks.Remove(position);
            spawnedChunks.Remove(chunkDictionary[position]);
        }
    }

    Key changes:

    1. Explicitly deactivate chunks
    2. Create a separate list to track chunks to unload
    3. Remove chunks from loadedChunks and spawnedChunks

    Would you like me to add some debug logging to help diagnose the issue?

Viewing 20 posts - 21 through 40 (of 47 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: