- Home /
A respawn script for enemies.
Hey guys, I've run into somewhat of a wall one might call it. I have a simple respawn script for my enemies in my level (currently a very very simple one, for testing purposes).
I have all enemies in a list.
The script works by the killed enemy sending it's id and also it's respawn time to two separate lists.
The respawn script then checks the id against the list with enemies and when the corresponding respawn time reaches zero, the exact same monster which was killed is respawned.
It's working great, but I just recently found out that if an enemy with a shorter respawn time than what's left on the previously killed enemies respawn time the list goes out of range.
Could someone take a look at the code and see if you can find out what I'm missing.
(MonsterMaster, handles spawning initially and then respawning monsters defined in the inspector)
The code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[System.Serializable]
public class MonsterMaster : MonoBehaviour {
public EnemyClass[] enemies;
public List<float> respawnTime;
public List<int> enemyIDs;
void Start () {
respawnTime = new List<float>();
enemyIDs = new List<int>();
for(int x = 0; x < enemies.Length; x++){
if(enemies[x].isSpawned == false){
GameObject enemy;
enemy = Instantiate(enemies[x].enemyPrefab, enemies[x].spawnPoint, Quaternion.identity) as GameObject;
enemies[x].isSpawned = true;
Enemy enemyScript;
enemyScript = enemy.GetComponent<Enemy>();
enemyScript.enemyId = enemies[x].id;
enemyScript.health = enemies[x].health;
enemyScript.enemyName = enemies[x].name;
enemyScript.enemyGuild = enemies[x].guild;
enemyScript.level = enemies[x].level;
enemyScript.exp = enemies[x].experience;
enemyScript.moveSpeed = enemies[x].moveSpeed;
enemyScript.maxMoveDistance = enemies[x].maxMoveDistance;
enemyScript.respawnTime = enemies[x].respawnTime;
enemyScript.loot = enemies[x].loot;
}
}
}
void Update () {
for(int x = 0; x < respawnTime.Count; x++){
respawnTime[x] -= Time.deltaTime;
for(int idCnt = 0; idCnt < enemyIDs.Count; idCnt++){
for(int cnt = 0; cnt < enemies.Length; cnt++){
/*error here*/ if(enemyIDs.Count != 0 && enemies[cnt].id == enemyIDs[idCnt] && enemies[cnt].isSpawned == false && respawnTime[x] <= 0){
GameObject enemy;
enemy = Instantiate(enemies[cnt].enemyPrefab, enemies[cnt].spawnPoint, Quaternion.identity) as GameObject;
enemies[cnt].isSpawned = true;
Enemy enemyScript;
enemyScript = enemy.GetComponent<Enemy>();
enemyScript.enemyId = enemies[cnt].id;
enemyScript.health = enemies[cnt].health;
enemyScript.enemyName = enemies[cnt].name;
enemyScript.enemyGuild = enemies[cnt].guild;
enemyScript.level = enemies[cnt].level;
enemyScript.exp = enemies[cnt].experience;
enemyScript.moveSpeed = enemies[cnt].moveSpeed;
enemyScript.maxMoveDistance = enemies[cnt].maxMoveDistance;
enemyScript.respawnTime = enemies[cnt].respawnTime;
enemyScript.loot = enemies[cnt].loot;
enemyIDs.RemoveAt(idCnt);
respawnTime.RemoveAt(x);
}
}
}
}
}
}
The error:
ArgumentOutOfRangeException: Argument is out of range. Parameter name: index System.Collections.Generic.List`1[System.Single].get_Item (Int32 index) (at /Applications/buildAgent/work/84669f285f6a667f/mcs/class/corlib/System.Collections.Generic/List.cs:633) MonsterMaster.Update () (at Assets/Scripts/Enemies/MonsterMaster.cs:42)
(mainly focusing on functionality at the moment) The game in it's current state: https://dl.dropboxusercontent.com/u/163931410/Awesome/Awesome.html
Any tips for improvements are also highly appreciated!
Thanks for taking your time! :)
That error means you are trying to access something at an index of a list that does not exist.
list = [0, 2, 6]
lol = list[3]
In this case list[3]
does not exist. Therefore the same error :)
Thanks for the quick reply!
I'm not sure how I'm going to solve this one however.
Example:
I kill enemy with id 2, got a respawn time of 10. It sends it's id to the ID List. It sends it's respawn time to the respawn List.
It's id should now be at index 0 of the id List and it's respawn time should now be at index 0 of the respawn List, correct?
If I then kill another enemy with id 3, respawn time of 2. It sends it's id to the same ID List, with index 1. It sends it's respawn time to the respawn List, index 1.
The first monster then spawns when the second monster's respawn time reaches 0 and the second monster spawns when the other respawn time reaches 0. (forgot to mention this in the question, sorry!)
So basically what's not working as I intended it to is the ID check.
Any help on this one is much much much appreciated!
Note: I'm very new to program$$anonymous$$g!
Thanks :)
I see nowhere where you add to the enemy id list. I'm guessing your problem is that your enemy id list is actually empty. Try just debugging the length of your lists and seeing if a problem arises there :)
Answer by jollz · Jun 30, 2013 at 12:08 PM
I just sat down and rewrote the whole thing and somehow I got it working properly!
Thanks Benproductions for the reply, and thanks to anyone who was trying to help but didn't get the time to reply!
Here's the rewritten code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[System.Serializable]
public class MonsterMaster : MonoBehaviour {
public EnemyClass[] enemies;
public List<float> respawnTime;
public List<int> enemyIDs;
void Start () {
respawnTime = new List<float>();
enemyIDs = new List<int>();
for(int x = 0; x < enemies.Length; x++){
if(enemies[x].isSpawned == false){
GameObject enemy;
enemy = Instantiate(enemies[x].enemyPrefab, enemies[x].spawnPoint, Quaternion.identity) as GameObject;
enemies[x].isSpawned = true;
Enemy enemyScript;
enemyScript = enemy.GetComponent<Enemy>();
enemyScript.enemyId = enemies[x].id;
enemyScript.health = enemies[x].health;
enemyScript.enemyName = enemies[x].name;
enemyScript.enemyGuild = enemies[x].guild;
enemyScript.level = enemies[x].level;
enemyScript.exp = enemies[x].experience;
enemyScript.moveSpeed = enemies[x].moveSpeed;
enemyScript.maxMoveDistance = enemies[x].maxMoveDistance;
enemyScript.respawnTime = enemies[x].respawnTime;
enemyScript.loot = enemies[x].loot;
}
}
}
void Update () {
for(int x = 0; x < respawnTime.Count; x++){
respawnTime[x] -= Time.deltaTime;
for(int respawnCnt = 0; respawnCnt < respawnTime.Count; respawnCnt++){
if(respawnTime[respawnCnt] <= 0){
for(int enemyCnt = 0; enemyCnt < enemies.Length; enemyCnt++){
if(enemies[enemyCnt].isSpawned == false && enemyIDs[respawnCnt] == enemies[enemyCnt].id){
Debug.Log (enemies[enemyCnt].id);
GameObject enemy;
enemy = Instantiate(enemies[enemyCnt].enemyPrefab, enemies[enemyCnt].spawnPoint, Quaternion.identity) as GameObject;
enemies[x].isSpawned = true;
Enemy enemyScript;
enemyScript = enemy.GetComponent<Enemy>();
enemyScript.enemyId = enemies[enemyCnt].id;
enemyScript.health = enemies[enemyCnt].health;
enemyScript.enemyName = enemies[enemyCnt].name;
enemyScript.enemyGuild = enemies[enemyCnt].guild;
enemyScript.level = enemies[enemyCnt].level;
enemyScript.exp = enemies[enemyCnt].experience;
enemyScript.moveSpeed = enemies[enemyCnt].moveSpeed;
enemyScript.maxMoveDistance = enemies[enemyCnt].maxMoveDistance;
enemyScript.respawnTime = enemies[enemyCnt].respawnTime;
enemyScript.loot = enemies[enemyCnt].loot;
}
}
respawnTime.RemoveAt(respawnCnt);
enemyIDs.RemoveAt(respawnCnt);
}
}
}
}
}
awesome technic dude ! don't $$anonymous$$d if I ever come to use it ? I'm having such a hard time trying to write a respawn enemy system that satisfies me ^^'
@RemDust Feel free to use it as you please, do note however that it was written quite some time ago :)
Actually, I don't like to use scripts I don't fully understand, and this is actually the case here ^^ but maybe if I don't find any other way to respawn my enemies properly soon, I'll come back to this.
Tank you so much !
Your answer
Follow this Question
Related Questions
A node in a childnode? 1 Answer
Character respawns invisable? 1 Answer
Spawning a new player instance (UNET) 3 Answers