Forum begins after the advertisement:


[Part 2] Error cannot generate map

Home Forums Video Game Tutorial Series Creating a Metroidvania in Unity [Part 2] Error cannot generate map

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #17988
    Hiếu Hoàng
    Level 10
    Silver Supporter (Patron)
    Helpful?
    Up
    0
    ::

    I am having problem with generating new map when running game, can someone help me. Here is the source code with video when I run game: MapController:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class MapController : MonoBehaviour
    {
        public List<GameObject> terrainChunks;
        public GameObject player;
        public float checkerRadius;
        public Vector3 noTerrainPosition;
        public LayerMask terrainMask;
        public GameObject currentChunk;
        PlayerMovement pm;
    
        [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()
        {
            pm = FindAnyObjectByType<PlayerMovement>();
        }
    
        void Update()
        {
            ChunkChecker();
            ChunkOptimzer();
        }
    
        void ChunkChecker()
        {
            if (!currentChunk)
            {
                return;
            }
    
            if (pm.moveDir.x > 0 && pm.moveDir.y == 0)
            {
                if (!Physics2D.OverlapCircle(currentChunk.transform.Find("Right").position, checkerRadius, terrainMask))
                {
                    noTerrainPosition = currentChunk.transform.Find("Right").position;  //Right
                    SpawnChunk();
                }
            }
            else if (pm.moveDir.x < 0 && pm.moveDir.y == 0)
            {
                if (!Physics2D.OverlapCircle(currentChunk.transform.Find("Left").position, checkerRadius, terrainMask))
                {
                    noTerrainPosition = currentChunk.transform.Find("Left").position;    //Left
                    SpawnChunk();
                }
            }
            else if (pm.moveDir.y > 0 && pm.moveDir.x == 0)
            {
                if (!Physics2D.OverlapCircle(currentChunk.transform.Find("Up").position, checkerRadius, terrainMask))
                {
                    noTerrainPosition = currentChunk.transform.Find("Up").position; //Up
                    SpawnChunk();
                }
            }
            else if (pm.moveDir.y < 0 && pm.moveDir.x == 0)
            {
                if (!Physics2D.OverlapCircle(currentChunk.transform.Find("Down").position, checkerRadius, terrainMask))
                {
                    noTerrainPosition = currentChunk.transform.Find("Down").position;    //Down
                    SpawnChunk();
                }
            }
            else if (pm.moveDir.x > 0 && pm.moveDir.y > 0)
            {
                if (!Physics2D.OverlapCircle(currentChunk.transform.Find("Right Up").position, checkerRadius, terrainMask))
                {
                    noTerrainPosition = currentChunk.transform.Find("Right Up").position;   //Right up
                    SpawnChunk();
                }
            }
            else if (pm.moveDir.x > 0 && pm.moveDir.y < 0)
            {
                if (!Physics2D.OverlapCircle(currentChunk.transform.Find("Right Down").position, checkerRadius, terrainMask))
                {
                    noTerrainPosition = currentChunk.transform.Find("Right Down").position;  //Right down
                    SpawnChunk();
                }
            }
            else if (pm.moveDir.x < 0 && pm.moveDir.y > 0)
            {
                if (!Physics2D.OverlapCircle(currentChunk.transform.Find("Left Up").position, checkerRadius, terrainMask))
                {
                    noTerrainPosition = currentChunk.transform.Find("Left Up").position;  //Left up
                    SpawnChunk();
                }
            }
            else if (pm.moveDir.x < 0 && pm.moveDir.y < 0)
            {
                if (!Physics2D.OverlapCircle(currentChunk.transform.Find("Left Down").position, checkerRadius, terrainMask))
                {
                    noTerrainPosition = currentChunk.transform.Find("Left Down").position; //Left down
                    SpawnChunk();
                }
            }
        }
    
        void SpawnChunk()
        {
            int rand = Random.Range(0, terrainChunks.Count);
            latestChunk = Instantiate(terrainChunks[rand], noTerrainPosition, 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);
                }
            }
        }
    }

    ChunkTrigger:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class ChunkTrigger : MonoBehaviour
    {
        MapController mc;
    
        public GameObject targetMap;
    
        void Start()
        {
            mc = FindAnyObjectByType<MapController>();
        }
    
        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.currentChunk = null;
                }
            }
        }
    }

    Video running:

    View post on imgur.com
    @Terence
    #17989
    Ser Apustaja
    Level 6
    AI Assistant
    (BETA)
    Helpful?
    Up
    0
    ::

    Based on the code you provided and the issue you’re facing with generating new maps, here are a few things you can check and potential fixes:

    1. Layer Mask Setup: Ensure that the terrainMask is properly set up in the Unity Inspector. This mask should include the layers that your terrain chunks are assigned to. If the mask does not include the correct layers, the Physics2D.OverlapCircle checks may always return false, preventing new chunks from being spawned.

    2. Chunk Positioning: In the SpawnChunk() method, double-check that the noTerrainPosition is being set correctly. If the position is incorrect or overlaps with existing terrain chunks, it may create issues. You may want to log the noTerrainPosition to ensure it’s being set as expected.

       void SpawnChunk()
       {
           int rand = Random.Range(0, terrainChunks.Count);
           latestChunk = Instantiate(terrainChunks[rand], noTerrainPosition, Quaternion.identity);
           spawnedChunks.Add(latestChunk);
           Debug.Log("Spawned chunk at position: " + noTerrainPosition);
       }
    3. Direction Logic: Ensure that the logic in ChunkChecker() is correctly identifying the direction of the player’s movement. You can log the pm.moveDir values to verify that they are set correctly from the PlayerMovement script.

    4. Optimization Logic: In the ChunkOptimzer() method, ensure that the optimizerCooldown is being reset correctly. If the cooldown is set to a very low value, it might not allow chunks to spawn frequently enough. Consider logging the optimizerCooldown to see how it changes over time.

    5. Check for Null References: Make sure that currentChunk is being set correctly in ChunkTrigger. If it’s not being set, ChunkChecker will return early without spawning new chunks. You can add debug logs to check if the player is entering and exiting the triggers correctly.

    6. Debugging: Add debug statements throughout your code to track the flow of execution and the values of variables. This can help identify where the issue occurs.

    7. Unity Version Issues: If you are using a newer version of Unity, ensure that there are no breaking changes related to the physics system or instantiation methods that may affect your code.

    Here’s an example of how to add some debug logs in the ChunkChecker() method:

    void ChunkChecker()
    {
        if (!currentChunk)
        {
            Debug.Log("Current chunk is null.");
            return;
        }
    
        Debug.Log("Checking chunks based on player movement: " + pm.moveDir);
    
        // Existing checks...
    }

    By implementing these checks and debug logs, you should be able to identify the cause of the issue more easily and ensure that new chunks are generated as expected. If the problem persists, please provide any specific errors or unexpected behavior you encounter.

    #17991
    Terence
    Level 31
    Keymaster
    Helpful?
    Up
    0
    ::

    Can you also post a screenshot of the Terrain Mask attribute on your MapController in the Inspector? What layers were selected on that variable?

    And what layer are the chunk prefabs assigned to?

Viewing 3 posts - 1 through 3 (of 3 total)
  • You must be logged in to reply to this topic.

Go to Login Page →


Advertisement below: