- Home /
Enemy Respawn Bug
When my enimes hit below 0 health I want them to be set inactive for a couple seconds then active again, I can not for the life of me get this to work.. I need help (IN C##) Heres the simple code I have.
public void respawn() {
transform.position = respawnhere;
transform.active = true;
}
public void despawn() {
transform.active = false;
}
IEnumerator Example() {
despawn();
yield return new WaitForSeconds(35);
respawn();
}
I'm not 100% sure, but I believe that since the script is on the enemy that's being disabled, the script is as well, so there's no way for it to call respawn(), as the function does not exist in the scene anymore while the object is inactive.
Although, what part isn't working for you, could you be more specific? Are you not able to deactivate at all? (I do believe .active is deprecated now...)
Oh that makes sense, the deactive part works perfect but when I try to bring the enemy back thats what doesnt work :/
Alright, well, the only real workaround I know of for this is to have the script on a parent object and use:
transform.GetChild(0).gameObject.SetActive(true/false);
This way you can enable and disable the sub-object without issue.
So just:
IEnumerator death()
{
transform.GetChild(0).gameObject.SetActive(false);
yield return new WaitForSeconds(35f);
transform.GetChild(0).gameObject.SetActive(true);
transform.GetChild(0).gameObject.transform.localPosition = respawnHere;
}
0 just means the first child object listed, so you increase the number to get an object further down a child list.
And no real need for the separate Respawn/Despawn() functions, the IEnumerator can take care of both, they aren't serving much use by being separate. Though if you have some need for that, then I'm sure you can work out how to split that back up into your separate functions.
The only real other way is to just have you script disable the sprite or mesh renderer for your object, as well as the collider and any other components you want disable, except for the object itself.
It needs to be on a script that is a parent object of the enemy. So just create an empty game object, put the enemy in it and put the script on that parent object.
Answer by Invertex · Jan 19, 2014 at 11:02 AM
I did an edit that changed the script up to work in an easier way after you must have read it. Although I don't see why it wouldn't be working for you, guess I'd need to see your scene. Anyway, I thought up an even simpler solution that offers you even more freedom. No parents needed.
Just create an Empty GameObject for your scene, and call it whatever you want, like deathObject or w/e.
Then attach this script: Respawner.cs
using UnityEngine;
using System.Collections;
public class Respawner : MonoBehaviour
{
static public Respawner respawner;
void Awake()
{
respawner = this.gameObject.GetComponent<Respawner>(); //declare this script to itself so that the static function can access it
}
public static void death(GameObject killObj,Vector3 position, float timeToWait) //this is static, so it can be called from anything else in the game without a GetComponent
{
respawner.StartCoroutine(respawner.deathRoutine(killObj,position,timeToWait)); //starting coroutine from within this gameobject.
}
IEnumerator deathRoutine(GameObject inputObj,Vector3 position, float timeToWait)
{
inputObj.SetActive(false);
yield return new WaitForSeconds(timeToWait);
inputObj.SetActive(true);
inputObj.transform.position = position;
}
}
Now, on your enemies, the ONLY thing you need to do is use:
Respawner.death(this.gameObject,respawnhere,35f);
You can also define the time differently on each enemy if you so choose, by feeding the function the time you want it to wait.
Answer by Grim_Darknight · Jan 20, 2014 at 10:16 AM
I think the best way to implement what you are talking about while making it reusable for multiple enemies would be:
[Enemy Controller] This will be your parent object, it will control spawning behaviour.
-->[E] [E] ....[E] These are the enemies, they all manage their own health and variables.
On the controller you can set up an array with all of your enemies:
public GameObject[] enemy;
then in your update for the controller you can do:
void Update()
{
foreach(GameObject enem in enemy)
{
if((health <= 0)&&( transform.active))
{
transform.active = false;
yield return new WaitForSeconds(35f);
health = 100;
}
else
{
transform.active = true;
}
}
}
this is a rough way that it can be done.
you could also set eah enemy to register the parent object and send a death message so that it only checks when an enemy dies, that could save a bit of proccessing over checking every update.
I am pretty sure lots of adjestments to my sample may be needed but I hope it helps with the issue.
Answer by thef1chesser · Jan 20, 2014 at 10:33 AM
I see a lot of different suggestions in the comments.
Seeing the original question... I have the idea using enabled in stead of transform.active might be more useful.
So it would be:
public void respawn() {
gameObject.transform.position = respawnhere;
gameObject.enabled = true;
}
public void despawn() {
gameObject.enabled = false;
}
IEnumerator Example() {
despawn();
yield return new WaitForSeconds(35);
respawn();
}
Im using C## and when I try to use enable i get an error
Your answer
Follow this Question
Related Questions
Gameobject Respawn 1 Answer
Respawn Enemy Prefab after its destroyed 1 Answer
[C#] Respawning system Enemies 0 Answers
Help with error when using instantiate to respawn an enemy. 0 Answers
SetActive Not Responding 3 Answers