Forum begins after the advertisement:


[Part 2] Issue with chunk loading

Home Forums Video Game Tutorial Series Creating a Rogue-like Shoot-em Up in Unity [Part 2] Issue with chunk loading

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author
    Posts
  • #15109
    Norman Harig
    Participant

    Hello there,

    I believe there’s an issue with how the chunk loading is handled in the game. Currently, when I move to the edge of a chunk (but still inside it), let’s say to the right, a new chunk spawns to the right. However, if I then press down at that edge, new chunks are only created on the “down edge” because the script checks the movement direction.

    This results in a gap to the right of the player, as chunks are not loaded in that direction unless the player moves specifically in that direction.

    How would you guys solve this? Would it not be better to check with the camera if the player is approaching the edge of chunks?

    #15110
    Terence
    Keymaster

    Hi Norman, there is a known issue with chunk generation when you move diagonally. This is addressed in the Part 11 video. I’ve timestamped the section for you on this link: https://youtu.be/4U_f_qjOpZE&t=20m53s

    Part 11 focuses a lot on fixing the various bugs with chunk generation that we had after Part 2 released.

    #15118
    Norman Harig
    Participant

    Hey,

    so this issue has nothing to do with diagonal movement and is not fixed in video 11. The issue is like I said, when you go i.e. to the right edge of a chunk and then go up or down. Nothing will spawn to the right. I fixed it in the script below. Also I fixed a bug where at the start of a game a chunk is spawned below the player without the player moving. Moreover I added that the first chunk is spawned at random. Most importantly I added a prallax effect. Meaning I added the possibility to have multiple alyers of backround. I am not that good at programming yet, but have a look:

    public class MapController : MonoBehaviour
    {
        public List<GameObject> FirstLayer;
        public List<GameObject> SecondLayer;
        public List<GameObject> ThirdLayer;
        public List<GameObject> FourthLayer;
    
        public GameObject player;
        public float checkerRadius;
        //public Vector3 noTerrainPosition;
        private LayerMask terrainMask;
    
        public List<GameObject> currentChunks;  
    
        [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;
    
        Vector3 playerLastPostiiton;
    
        private void Awake()
        {
            InitialChunkSpawner();
        }
    
        private Dictionary<int, LayerMask> layerMasks;
    
        void Start()
        {
            playerLastPostiiton = player.transform.position;
    
            // Initialize layer masks
            layerMasks = new Dictionary<int, LayerMask>
            {
                { 1, LayerMask.GetMask("Layer_1") },
                { 2, LayerMask.GetMask("Layer_2") },
                { 3, LayerMask.GetMask("Layer_3") },
                { 4, LayerMask.GetMask("Layer_4") }
            };
        }
    
        void Update()
        {
            ChunkChecker();
            ChunkOptimzer();
        }
    
        private void InitialChunkSpawner()
        {
            SpawnChunk_Layer1(player.transform.position);
            SpawnChunk_Layer2(player.transform.position);
            SpawnChunk_Layer3(player.transform.position);
            SpawnChunk_Layer4(player.transform.position);
        }
    
        private void CheckAndSpawnChunk(GameObject chunk, string direction, int layer)
        {
            if(chunk && !Physics2D.OverlapCircle(chunk.transform.Find(direction).position, checkerRadius, layerMasks[layer]))
            {
    
                if (chunk.GetComponent<ParralaxEffect>().layerNumber == 1)
                {
                    SpawnChunk_Layer1(chunk.transform.Find(direction).position);
                }
                else if (chunk.GetComponent<ParralaxEffect>().layerNumber == 2)
                {
                    SpawnChunk_Layer2(chunk.transform.Find(direction).position);
                }
                else if (chunk.GetComponent<ParralaxEffect>().layerNumber == 3)
                {
                    SpawnChunk_Layer3(chunk.transform.Find(direction).position);
                }
                else if (chunk.GetComponent<ParralaxEffect>().layerNumber == 4)
                {
                    SpawnChunk_Layer4(chunk.transform.Find(direction).position);
                }
    
            }
        }
    
        void ChunkChecker()
        {
            if (currentChunks == null || currentChunks.Count == 0)
            {
                return;
            }
    
            Vector3 moveDir = player.transform.position - playerLastPostiiton;
    
            // Only proceed if the player has actually moved
            if (moveDir.magnitude < 0.01f)
            {
                return;
            }
    
            playerLastPostiiton = player.transform.position;
    
            string directionName = GetDirectionName(moveDir);
    
            foreach (GameObject chunk in currentChunks)
            {
                int layer = chunk.GetComponent<ParralaxEffect>().layerNumber;
    
                CheckAndSpawnChunk(chunk, directionName, layer);
                // Ensure neighboring chunks are checked and spawned
                CheckAndSpawnAdjacentChunks(chunk, directionName, layer);
            }
    
        }
    
        void CheckAndSpawnAdjacentChunks(GameObject chunk, string directionName, int layer)
        {
            if (directionName.Contains("Up"))
            {
                CheckAndSpawnChunk(chunk, "Up", layer);
                CheckAndSpawnChunk(chunk, "Up Right", layer);
                CheckAndSpawnChunk(chunk, "Up Left", layer);
            }
            if (directionName.Contains("Down"))
            {
                CheckAndSpawnChunk(chunk, "Down", layer);
                CheckAndSpawnChunk(chunk, "Down Right", layer);
                CheckAndSpawnChunk(chunk, "Down Left", layer);
            }
            if (directionName.Contains("Right"))
            {
                CheckAndSpawnChunk(chunk, "Right", layer);
                CheckAndSpawnChunk(chunk, "Down Right", layer);
                CheckAndSpawnChunk(chunk, "Up Right", layer);
            }
            if (directionName.Contains("Left"))
            {
                CheckAndSpawnChunk(chunk, "Left", layer);
                CheckAndSpawnChunk(chunk, "Down Left", layer);
                CheckAndSpawnChunk(chunk, "Up Left", layer);
            }
        }
    
        string GetDirectionName(Vector3 direction)
        {
            direction = direction.normalized;
    
            if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y))
            {
                // horizontal movement
                if (direction.y > 0.5f)
                {
                    return direction.x > 0 ? "Up Right" : "Up Left";
                }
                else if (direction.y < -0.5f)
                {
                    return direction.x > 0 ? "Down Right" : "Down Left";
                }
                else
                {
                    return direction.x > 0 ? "Right" : "Left";
                }
            }
            else
            {
                // move verticaly
                if (direction.x > 0.5f)
                {
                    return direction.y > 0 ? "Up Right" : "Down Left";
                }
                else if (direction.x < -0.5f)
                {
                    return direction.y > 0 ? "Up Left" : "Down Left";
                }
                else
                {
                    return direction.y > 0 ? "Up" : "Down";
                }
            }
        }
    
        void SpawnChunk_Layer1(Vector3 spawnPosition)
        {
            Debug.Log("FirstLayerSpawend");
            int rand = Random.Range(0, FirstLayer.Count);
            latestChunk = Instantiate(FirstLayer[rand], spawnPosition, Quaternion.identity);
            spawnedChunks.Add(latestChunk);
    
        }
    
        void SpawnChunk_Layer2(Vector3 spawnPosition)
        {
            int rand = Random.Range(0, SecondLayer.Count);
            latestChunk = Instantiate(SecondLayer[rand], spawnPosition, Quaternion.identity);
            spawnedChunks.Add(latestChunk);
        }
    
        void SpawnChunk_Layer3(Vector3 spawnPosition)
        {
            int rand = Random.Range(0, ThirdLayer.Count);
            latestChunk = Instantiate(ThirdLayer[rand], spawnPosition, Quaternion.identity);
            spawnedChunks.Add(latestChunk);
        }
    
        void SpawnChunk_Layer4(Vector3 spawnPosition)
        {
            if (FourthLayer.Count > 0)
            {
                int rand = Random.Range(0, FourthLayer.Count);
                latestChunk = Instantiate(FourthLayer[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);
                }
            }
        }
    public class ParralaxEffect : MonoBehaviour
    {
        private Vector3 initialPosition;
        private Vector3 initialCamPosition;
        public GameObject cam; // The camera
        public float parallaxFactor; // How much this layer should parallax (0 = no parallax, 1 = full parallax)
    
        void Start()
        {
            initialPosition = transform.position;
            if (cam == null)
            {
                cam = Camera.main.gameObject; // Default to the main camera if none is specified
            }
            initialCamPosition = cam.transform.position;
        }
    
        void LateUpdate()
        {
            // Calculate the distance the camera has moved from its initial position
            Vector3 cameraDelta = cam.transform.position - initialCamPosition;
    
            // Apply the parallax effect based on this delta
            float distX = cameraDelta.x * parallaxFactor;
            float distY = cameraDelta.y * parallaxFactor;
    
            // Update the position of the background layer
            transform.position = new Vector3(initialPosition.x + distX, initialPosition.y + distY, initialPosition.z);
        }
    
        public int layerNumber;
    
    }
    #15119
    Terence
    Keymaster

    Norman, nice that you managed to implement the parallax effect.

    How do you get the right edge trigger to activate when moving down? Is it by getting enemies to push you?

    #15122
    Norman Harig
    Participant

    Hey,

    I use smaller tiles then you, so maybe this is why this has come to my attention.

    The issue is that if I move down, the RIGHT chunk spawning is NOT triggered because I dont press right. So if you go to the right edge of the tile (but still in the tile) and press down, there is no chunk on the right in subsequent areas.

    Here is how I solved it:

    CheckAndSpawnChunk(chunk, "Up Right", layer);
     CheckAndSpawnChunk(chunk, "Up Left", layer);
    #15126
    Terence
    Keymaster

    Thanks for sharing your code here Norman. For anyone else who’s reading this topic, I’ve highlighted the parts Norman has added (in the MapController script) below:

        void ChunkChecker()
        {
            if (currentChunks == null || currentChunks.Count == 0)
            {
                return;
            }
    
            Vector3 moveDir = player.transform.position - playerLastPostiiton;
    
            // Only proceed if the player has actually moved
            if (moveDir.magnitude < 0.01f)
            {
                return;
            }
    
            playerLastPostiiton = player.transform.position;
    
            string directionName = GetDirectionName(moveDir);
    
            foreach (GameObject chunk in currentChunks)
            {
                int layer = chunk.GetComponent().layerNumber;
    
                CheckAndSpawnChunk(chunk, directionName, layer);
                // Ensure neighboring chunks are checked and spawned
                CheckAndSpawnAdjacentChunks(chunk, directionName, layer);
            }
    
        }
    
        void CheckAndSpawnAdjacentChunks(GameObject chunk, string directionName, int layer)
        {
            if (directionName.Contains("Up"))
            {
                CheckAndSpawnChunk(chunk, "Up", layer);
                CheckAndSpawnChunk(chunk, "Up Right", layer);
                CheckAndSpawnChunk(chunk, "Up Left", layer);
            }
            if (directionName.Contains("Down"))
            {
                CheckAndSpawnChunk(chunk, "Down", layer);
                CheckAndSpawnChunk(chunk, "Down Right", layer);
                CheckAndSpawnChunk(chunk, "Down Left", layer);
            }
            if (directionName.Contains("Right"))
            {
                CheckAndSpawnChunk(chunk, "Right", layer);
                CheckAndSpawnChunk(chunk, "Down Right", layer);
                CheckAndSpawnChunk(chunk, "Up Right", layer);
            }
            if (directionName.Contains("Left"))
            {
                CheckAndSpawnChunk(chunk, "Left", layer);
                CheckAndSpawnChunk(chunk, "Down Left", layer);
                CheckAndSpawnChunk(chunk, "Up Left", layer);
            }
        }

    P.S. I think you should be able to remove the “Up”, “Down”, “Left” and “Right” spawns in CheckAndSpawnAdjacentChunks(), since they should already be called in the ChunkChecker() function above of the CheckAndSpawnAdjacentChunks() call.

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

Go to Login Page →


Advertisement below: