Forum begins after the advertisement:
[Part 11] Chunk not loading correctly and enemies are multiplied when spawning
Home › Forums › Video Game Tutorial Series › Creating a Rogue-like Shoot-em Up in Unity › [Part 11] Chunk not loading correctly and enemies are multiplied when spawning
- This topic has 5 replies, 2 voices, and was last updated 1 month, 1 week ago by ThatOneGuy.
-
AuthorPosts
-
October 10, 2024 at 7:34 am #16016::
For the first issue, chunk loading diagonally is working fine but walking straight and the chunks are not loading correctly
Video:
Screenshot of the Trigger Inspector:
For the second issue, for some reason when enemies in a wave are being spawned, they get multiplied by 2
Code:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class EnemySpawner : MonoBehaviour { [System.Serializable] public class Wave { public string waveName; public List<EnemyGroup> enemyGroups; //list of groups of enemies to spawn in a wave public int waveQuota; //Total number of enemies to spawn in a wave public float spawnInterval; //interval at which to spawn enemies public int spawnCount; //number of enemies already spawned in a wave } [System.Serializable] public class EnemyGroup { public string enemyName; public int enemyCount; //Then number of enemiues to spawn in a wave public int spawnCount;// number of specific enemies type already spawned in a wave public GameObject enemyPrefab; } public List<Wave> waves; //A list of all the waves in the game public int currentWaveCount; //this is the index of the current wave (P.S. list always starts from 0) [Header("Spawner Attributes")] float spawnTimer; //Timer use to determine when to spawn the next enemy public int enemiesAlive; //number of enemies alive public int maxEnemiesAllowed; //maximum number of enemies allowed on the map public bool maxEnemiesReached = false; //Flag that indicates if the maximum number of enemies has been reached public float waveInterval; //inverval between each wave bool isWaveActive = false; [Header("Spawn Positions")] public List<Transform> relativeSpawnPoints; //List to store all the relative spawn points of enemies Transform player; // Start is called before the first frame update void Start() { player = FindObjectOfType<PlayerStats>().transform; CalculateWaveQuota(); } // Update is called once per frame void Update() { if(currentWaveCount < waves.Count && waves[currentWaveCount].spawnCount == 0 && !isWaveActive) //Checks if the wave has ended and the next wave should start { StartCoroutine(BeginNextWave()); } spawnTimer += Time.deltaTime; //Checks to see if its time to spawn the next enemy if(spawnTimer >= waves[currentWaveCount].spawnInterval) { spawnTimer = 0f; SpawnEnemies(); } } IEnumerator BeginNextWave() { isWaveActive = true; //Wave for 'waveInterval' seconds before starting the next wave yield return new WaitForSeconds(waveInterval); //checks if there are more waves to start after the current wave, move on to the next wave if(currentWaveCount < waves.Count - 1) { isWaveActive = false; currentWaveCount++; CalculateWaveQuota(); } } void CalculateWaveQuota() { int currentWaveQuota = 0; foreach (var enemyGroup in waves[currentWaveCount].enemyGroups) //foreach loops that goes through all the enemy groups in the current wave count element of the waves array { currentWaveQuota += enemyGroup.enemyCount;//Add the enemy count of the current enemy groupd to the current wave quota } waves[currentWaveCount].waveQuota = currentWaveQuota; //sets the wave quota of the current wave count element in the wave array tot he current wave quota Debug.LogWarning(currentWaveQuota); } /// <summary> /// This method will stop spawning enemies if the amount of enemies on the map is maximum /// The method will only spawn enemies in a particular wave until it is time for the next wave's enemies to be spawned /// </summary> void SpawnEnemies()//method { if (waves[currentWaveCount].spawnCount < waves[currentWaveCount].waveQuota && !maxEnemiesReached) //checks if the minimum number of enemies in the current wave has been spawned { //Spawn each type of enemy until the quota is filled foreach (var enemyGroup in waves[currentWaveCount].enemyGroups) //loops each enemy group in the waves current wave count { //checks if the minimum number of enemies of this type have been spawned if (enemyGroup.spawnCount < enemyGroup.enemyCount) //checks if the minimum number of enemies of this type have been spawned by comparing the enemy group spawncount to enemy group enemy count { //Spawn the enemy at a random position close to the player Instantiate(enemyGroup.enemyPrefab, player.position + relativeSpawnPoints[Random.Range(0, relativeSpawnPoints.Count)].position, Quaternion.identity); //generates random x and y coordinates and storing them in a vector2 //adds the players x and y position to the randomised coordinates such that they are relative to ensure enemies spawn relative to the players movement Vector2 spawnPosition = new Vector2(player.transform.position.x + Random.Range(-10f, 10f), player.transform.position.y + Random.Range(-10f, 10f)); Instantiate(enemyGroup.enemyPrefab, spawnPosition, Quaternion.identity); enemyGroup.spawnCount++; //Increment to keep track enemy spawn waves[currentWaveCount].spawnCount++; //Increment to keep track of wave count enemiesAlive++; //Increment to keep count of enemies alive //limits the number of enemies that can be spawned at once if (enemiesAlive >= maxEnemiesAllowed) { maxEnemiesReached = true; return; } } } } } //Call this function when an enemy is killed public void OnEnemyKilled() { //Decrement the number of enemies alive enemiesAlive--; //Reset the maxEnemiesReached flag if the number of enemies alive has dropped below the maximum amount if (enemiesAlive < maxEnemiesAllowed) { maxEnemiesReached = false; } } }
October 10, 2024 at 5:24 pm #16020::Forgot to add my MapController script
using System.Collections; using System.Collections.Generic; using UnityEngine; public class MapController : MonoBehaviour { //Store prefabs for the terrainchunks public List<GameObject> terrainChunks; //references the player public GameObject player; //checks the radius public float checkerRadius; //track which layer is the terrain and which is not the terrain public LayerMask terrainMask; //reference to access variables public GameObject currentChunk; Vector3 playerLastPosition; [Header("Optimization")] //stores the current chunks public List<GameObject> spawnedChunks; //last chunk that was spawned GameObject latestChunk; //Max optimization distance //used to set the max distance for each of the chunk from player public float maxOpDist; //Must be greater than the length and width of the tilemap //references the current distance for each chunks float opDist; float optimizerCooldown; public float optimizerCooldownDur; // Start is called before the first frame update void Start() { playerLastPosition = player.transform.position; } // Update is called once per frame void Update() { ChunkChecker(); ChunkOptimizer(); } 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"); } if (directionName.Contains("Down")) { CheckAndSpawnChunk("Down"); } if (directionName.Contains("Right")) { CheckAndSpawnChunk("Right"); } if (directionName.Contains("Left")) { CheckAndSpawnChunk("Left"); } } 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 ? "Right Up" : "Left Up"; } else if (direction.y < -0.5f) { //also moving downwards return direction.x > 0 ? "Right Down" : "Left Down"; } else { //moving straight horizontally return direction.x > 0 ? "Right" : "Left"; } } else { //moving vertically more than vertically if (direction.x > 0.5f) { //also moving right return direction.y > 0 ? "Right Up" : "Right Down"; } else if (direction.x < -0.5f) { //also moving left return direction.y > 0 ? "Left Up" : "Left Down"; } 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 ChunkOptimizer() { optimizerCooldown -= Time.deltaTime; if(optimizerCooldown <= 0f) { optimizerCooldown = optimizerCooldownDur; } else { return; } //for loop foreach (GameObject chunk in spawnedChunks) { //distance of the chunk that is being checked opDist = Vector3.Distance(player.transform.position, chunk.transform.position); //checks if chunk dist is more than the max optimization dist and disable it if it is if (opDist > maxOpDist) { chunk.SetActive(false); } else { chunk.SetActive(true); } } } }
October 11, 2024 at 12:40 am #16023::This is a known bug with the
MapController
. I’ll be improving on the map generation system soon. For now, here’s an easy (but slightly inefficient) fix. Change the highlighted portion of theChunkChecker()
function.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"); } }
What we’re doing is instead of only checking the direction we are moving in, we are checking the diagonals as well.
October 11, 2024 at 7:39 am #16028::Got it. Thank you so much. About the second issue, I can’t seem to figure out the issue been trying to troubleshoot it but it still multiplies the enemy in the waves to 2
October 11, 2024 at 3:50 pm #16033::That’s because you call
Instantiate
twice inSpawnEnemy()
:void SpawnEnemies()//method { if (waves[currentWaveCount].spawnCount < waves[currentWaveCount].waveQuota && !maxEnemiesReached) //checks if the minimum number of enemies in the current wave has been spawned { //Spawn each type of enemy until the quota is filled foreach (var enemyGroup in waves[currentWaveCount].enemyGroups) //loops each enemy group in the waves current wave count { //checks if the minimum number of enemies of this type have been spawned if (enemyGroup.spawnCount < enemyGroup.enemyCount) //checks if the minimum number of enemies of this type have been spawned by comparing the enemy group spawncount to enemy group enemy count { //Spawn the enemy at a random position close to the player
Instantiate(enemyGroup.enemyPrefab, player.position + relativeSpawnPoints[Random.Range(0, relativeSpawnPoints.Count)].position, Quaternion.identity);//generates random x and y coordinates and storing them in a vector2 //adds the players x and y position to the randomised coordinates such that they are relative to ensure enemies spawn relative to the players movement Vector2 spawnPosition = new Vector2(player.transform.position.x + Random.Range(-10f, 10f), player.transform.position.y + Random.Range(-10f, 10f)); Instantiate(enemyGroup.enemyPrefab, spawnPosition, Quaternion.identity); enemyGroup.spawnCount++; //Increment to keep track enemy spawn waves[currentWaveCount].spawnCount++; //Increment to keep track of wave count enemiesAlive++; //Increment to keep count of enemies alive //limits the number of enemies that can be spawned at once if (enemiesAlive >= maxEnemiesAllowed) { maxEnemiesReached = true; return; } } } } }October 12, 2024 at 12:52 am #16040 -
AuthorPosts
- You must be logged in to reply to this topic.
Advertisement below: