cant delay with WaitForSeconds C#

Hi there!

Currently I am working on a respawn system and Show End Screen system for my android game!!

That is, if a player dies anywhere. The Prop will make a notification
using the Notification to the PlayerManager that the player has died.

The logic for Respawn system is simple.

  1. Player Dies, disable the player.
  2. Wait at player death position for 1 sec
  3. Check if player life is below zero or not
  4. If zero, stop respawn and show endscreen.
  5. If not zero, Move player to active Checkpoint position, and respawn
  6. Wait for 0.5 sec, decrement lives by 1, and enable the player.

This is the full logic of the whole code.

This logic uses NotificationCenter.cs to work correctly, so that PlayerManager listens for “PlayerDied” notification.

Any prop will post this notification anytime player triggers the prop for death.


The problem is everything here seem to work out exactly as planned only when the yield statements are removed.

If I yield for certain time the Debug message doesn’t prop at all.

Debug.LogError ( "PD Respawning the player" );

The above Error/Message do show up, but the Respawn() and the ShowEndScreen() method do not run at all. Proved as non of their Debug message is shown at all.

So problem is somewhere in the yield statements, can someone direct me on how to fix that?

Three scripts used!! All listed below!!



using UnityEngine;
    using System.Collections;
    
    public class PlayerManager : MonoBehaviour {
    	
    	public GameObject player;
    	public PlayerProperties playerProperties;
    	public GameObject activeCheckpoint;
    	
    	// Use this for initialization
    	void Start ()
    	{
    		// Add a observer for notification on when player dies
    		NotificationCenter.DefaultCenter.AddObserver(this,"PlayerDied");
    		
    		// Check if player is set or not
    		if(!player)
    		{
    			player = GameObject.FindGameObjectWithTag("Bounce");
    			
    			playerProperties = player.GetComponent < PlayerProperties > ();
    		}
    	}
    	
    	void PlayerDied ()
    	{
    		
    		
    		// Check for player lives, 0 or not                
    		if ( !(playerProperties.lives >= 0)   )
    		{
    			Debug.LogError ( "PD Showing End screen" );
    			showEndScreen();			
    		}
    		
    		if ( playerProperties.lives >= 0  )
    		{		
    			Debug.LogError ( "PD Respawning the player" );
    			// Respawn the player
    			Respawn ();
    		}
    		
    		
    		
    	}
    	
    	IEnumerable Respawn ()
    	{
    		// Firstly Disable the player
    		player.SetActiveRecursively ( false );
    		
    		// Decrement one life
    		playerProperties.lives--;
    		
    		// Wait for 1 sec
    		yield return new WaitForSeconds ( 1f );
    		
    		// Change player location to active checkpoint
    		player.transform.position = activeCheckpoint.transform.position;
    		
    		// Wait for 0.5 sec
    		yield return new WaitForSeconds ( 0.5f );
    		
    		// Enable the player
    		player.SetActiveRecursively ( true );
    		
    		Debug.LogError ( "Respawning the player" );
    		// Wait for some time
    			
    		// Then check for life of player
    		// If life still exists, respawn at checkpoint
    		// Else show Failed Menu
    	}
    	
    	void showEndScreen()
    	{
    		// Firstly Disable the player
    		player.SetActiveRecursively ( false );
    		
    		// Wait for 1 sec
    		//yield return new WaitForSeconds ( 1f );
    		
    		// Remove the oberserver
    		NotificationCenter.DefaultCenter.RemoveObserver (this,"PlayerDied");
    		
    		Debug.LogError ( "Showing End screen" );
    	}
    	
    }



    using UnityEngine;
    using System.Collections;
    
    public class SpikeScript : MonoBehaviour 
    {
    	
    	// Method to check what triggers the spikes
    	void OnTriggerEnter ( Collider other )
    	{
    		// check if trigers is from player or not
    		if ( other.gameObject.CompareTag ( "Bounce" ) )
    		{
    			// Post a notification saying the player died
    			NotificationCenter.DefaultCenter.PostNotification(this,"PlayerDied");
    			
    			return;
    		}
    	}
    	
    	
    }



    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
     
    public class NotificationCenter : MonoBehaviour
    {
        private static NotificationCenter defaultCenter;
        public static NotificationCenter DefaultCenter {
    		get {
    			if (!defaultCenter) {
    				GameObject notificationObject = new GameObject ("Default Notification Center");
     
    				defaultCenter = notificationObject.AddComponent<NotificationCenter> ();
    			}
     
                return defaultCenter; 
    		}
        }
     
     
     
        // Our hashtable containing all the notifications.  Each notification in the hash table is an ArrayList that contains all the observers for that notification.
    	Hashtable notifications = new Hashtable();
     
    	// AddObserver includes a version where the observer can request to only receive notifications from a specific object.  We haven't implemented that yet, so the sender value is ignored for now.
    	public void AddObserver (Component observer, string name) { AddObserver(observer, name, null); }
    	public void AddObserver (Component observer, string name, Component sender) {
    		// If the name isn't good, then throw an error and return.
    		if (string.IsNullOrEmpty (name)) { Debug.Log ("Null name specified for notification in AddObserver."); return; }
    		// If this specific notification doesn't exist yet, then create it.
    		if (notifications[name] == null) {
    			notifications[name] = new List<Component>();
    		}
     
    		List<Component> notifyList = notifications[name] as List<Component>;
     
    		// If the list of observers doesn't already contain the one that's registering, the add it.
    		if (!notifyList.Contains(observer)) { notifyList.Add(observer); }
    	}
     
     
    	public void RemoveObserver (Component observer, string name)
    	{
    		List<Component> notifyList = (List<Component>)notifications[name];
     
    		// Assuming that this is a valid notification type, remove the observer from the list.
    		// If the list of observers is now empty, then remove that notification type from the notifications hash. This is for housekeeping purposes.
    		if (notifyList != null) {
    			if (notifyList.Contains(observer)) { notifyList.Remove(observer); }
    			if (notifyList.Count == 0) { notifications.Remove(name); }
    		}
    	}
     
    	// PostNotification sends a notification object to all objects that have requested to receive this type of notification.
    	// A notification can either be posted with a notification object or by just sending the individual components.
     
    	public void PostNotification (Component aSender, string aName) { PostNotification(aSender, aName, null); }
        public void PostNotification (Component aSender, string aName, Hashtable aData) { PostNotification(new Notification(aSender, aName, aData)); }
    	public void PostNotification (Notification aNotification)
    	{
    		// First make sure that the name of the notification is valid.
    		//Debug.Log("sender: " + aNotification.name);
    		if (string.IsNullOrEmpty (aNotification.name)) {
    			Debug.Log ("Null name sent to PostNotification.");
    			return;
    		}
    		// Obtain the notification list, and make sure that it is valid as well
    		List<Component> notifyList = (List<Component>) notifications [aNotification.name];
    		if (notifyList == null) {
    			Debug.Log ("Notify list not found in PostNotification: " + aNotification.name);
    			return;
    		}
     
    		// Create an array to keep track of invalid observers that we need to remove
    		List<Component> observersToRemove = new List<Component> ();
     
    		// Itterate through all the objects that have signed up to be notified by this type of notification.
    		foreach (Component observer in notifyList) {
    			// If the observer isn't valid, then keep track of it so we can remove it later.
    			// We can't remove it right now, or it will mess the for loop up.
    			if (!observer) { observersToRemove.Add(observer); }
    			else {
    				// If the observer is valid, then send it the notification. The message that's sent is the name of the notification.
    				observer.SendMessage(aNotification.name, aNotification, SendMessageOptions.DontRequireReceiver);
    			}
    	}
     
    		// Remove all the invalid observers
    		foreach (Component observer in observersToRemove) {
    			notifyList.Remove(observer);
    		}
    	}
     
    	// The Notification class is the object that is send to receiving objects of a notification type.
    	// This class contains the sending GameObject, the name of the notification, and optionally a hashtable containing data.
    public class Notification {
     
    		//public Notification (GameObject aSender, string aName, Hashtable aData)
    		//{
    		//	throw new System.NotImplementedException ();
    		//}
     
        public Component sender;
        public string name;
        public Hashtable data;
        public Notification (Component aSender, string aName) { sender = aSender; name = aName; data = null; }
        public Notification (Component aSender, string aName, Hashtable aData) { sender = aSender; name = aName; data = aData; }
     
     
    }
    }

When calling a coroutine in C#, you need to use the StartCoroutine function.

So this:

Respawn();

Should probably look like this:

StartCoroutine(Respawn());

(UnityScript takes care of that for you; it’s one of a few gotchas when switching from JS to C#.)

You could not use the yield function and instead use InvokeRepeating()
Player Dies, disable the player.
Wait at player death position for 1 sec
Check if player life is below zero or not
If zero, stop respawn and show endscreen.
If not zero, Move player to active Checkpoint position, and respawn
Wait for 0.5 sec, decrement lives by 1, and enable the player.

Here is some pseudocode

void Update()
{
if (lives <= 0)
{
player.enabled = false;
checkRespawn();
}

void checkRespawn()
{
CancelInvoke(“checkRespawn”);

if (health <= 0)
     endScreen.enabled = true;
else
    InvokeRepeating("Respawn", 0.5, 1)

}

void Respawn()
{
    CancelInvoke("Respawn");
    player.enabled = true;
    player.transform.position = activeCheckpoint.transform.position;
}

Anywho I am not sure if that is going to work as I just did it in the comment box but I hope I can help clear it up a bit. Good Luck!