- Home /
The question is answered, right answer was accepted
Coroutine set up but doesn't seem to be working, what am i doing wrong?
hello I have some trouble with this coroutine, from what i read around and in the manual it should be in the right format but unity tells me it cannot be started. I thought to use it to take away the collider in order to make the player invincible for half second after respawn but the collider never get active after that time. I did use a serialized game object for player cause unity does not allow to destroy a prefab, what am i doing wrong thank you
[SerializeField] GameObject explosionPreFab;
public GameObject player;
[SerializeField] Vector3 respawnPoint;
private void Start()
{
respawnPoint.z = -0.5f;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Lake"))
{
LevelManager.lives--;
Destroy(gameObject);
var explosionPlace = transform.position;
var Explosion = Instantiate(explosionPreFab, explosionPlace, Quaternion.identity);
Destroy(Explosion, 0.2f);
player = Instantiate(player, respawnPoint, Quaternion.identity);
player.GetComponent<Movement>().enabled = true;
player.GetComponent<CapsuleCollider2D>();
player.GetComponent<CapsuleCollider2D>().enabled = false;
StartCoroutine(Inv());
}
IEnumerator Inv()
{
yield return new WaitForSeconds(0.5f);
player.GetComponent<CapsuleCollider2D>().enabled = true;
}
}
Answer by Bunny83 · Nov 13, 2021 at 03:29 PM
Those two lines do not work together:
Destroy(gameObject);
// [ ... ]
StartCoroutine(Inv());
You start the coroutine on this gameobject's monobehaviour instance which you just destroyed. When you destroy a gameobject or deactivate it, all coroutines would die with it.
You have two options here. Either don't destroy this gameobject immediately and wait for the coroutine to finish, or the better approach, move the coroutine onto the player since it's only relevant to the player anyways. One of the point of using OOP is to have seperation of concerns. Currently you have another object (this one) to take care of a property change of another object (the new player object). While this object can initiate a certain action, the actual changes should be done on the new player object.
We don't know where this script is attached to, how it's named and in general what its purpose is since we only see a part of it. However I guess that player object you instantiate would have some behaviour scripts as well which could take care of the disabling and re-enabling of the collider
Finally it's a very bad habit to do
player = Instantiate(player, ....
Assuming "player" is a prefab, you just reused the player member variable to hold the newly created instance. So the purpose of the variable changed and the original reference is lost. You really should avoid such usecases. It can easily being overlooked when you come back to the code in 6 month and suddenly something strange happens because you replaced that reference. Use local variables for such things.
thank you Bunny, i am very new to all this , and i really appreciate the time you spent to show me the way.
this script is attached to the player, and i did put player = Instantiate... because if i did not do that unity was saying something about the impossibility of destroying a prefab, and if i wanted to do that i had to do destroy immediately.
i thought that the coroutine was referring to the new instance of the player not the one that just died.
if i get it , do i put this coroutine on the prefab so each time is respawned its collider will be off for the time due?