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
- This topic has 5 replies, 2 voices, and was last updated 5 months ago by Terence.
-
AuthorPosts
-
June 18, 2024 at 5:42 am #15109::
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?
June 18, 2024 at 11:02 am #15110::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.
June 19, 2024 at 6:53 pm #15118::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; }
June 20, 2024 at 3:08 pm #15119::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?
June 20, 2024 at 11:58 pm #15122::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);
June 21, 2024 at 7:42 pm #15126::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 theChunkChecker()
function above of theCheckAndSpawnAdjacentChunks()
call. -
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: