How do I use yield in a C# RPC function?

Hi. I tried to convert javascript to C# with Networking sample.

My code almost works, but some code doesn’t work in NetworkLevelLoad.js (RPC function).

//NetworkLevelLoad.js

@RPC
function LoadLevel (level : String, levelPrefix : int)
{
    // omitted code

    Application.LoadLevel(level);
    yield;
    yield;

    // Allow receiving data again
    Network.isMessageQueueRunning = true;
    // Now the level has been loaded and we can start sending out data
    Network.SetSendingEnabled(0, true);

    // Notify our objects that the level and the network is ready
    for (var go in FindObjectsOfType(GameObject))
        go.SendMessage("OnNetworkLoadedLevel", SendMessageOptions.DontRequireReceiver); 
}

I convert yield; to yield return 0;, and edited LoadLevel function to IEnumerator LoadLevel. (Of course I converted other lines to C# too.)

But at runtime, after first yield return 0, script is ended and Network.IsMessageQueueRunning is not performed. How can I edit this script for work fine?

Thanks.

I’m currently struggling with the same task of converting the networking example to C#

The problem is that yield containing functions must return an Enumerator but RPC functions must return void.

The following code works for me.

[RPC]
public void LoadLevel(string level, int levelPrefix)
{
  StartCoroutine(loadLevel(level, levelPrefix));
}

private IEnumerator loadLevel(string level, int levelPrefix)
{
  // omitted code

  Application.LoadLevel(level);
  yield return new WaitForEndOfFrame();
  yield return new WaitForEndOfFrame();

  // Allow receiving data again
  Network.isMessageQueueRunning = true;
  // Now the level has been loaded and we can start sending out data
  Network.SetSendingEnabled(0, true);

  // Notify our objects that the level and the network is ready
  foreach (GameObject go in FindObjectsOfType(typeof(GameObject)))
    go.SendMessage("OnNetworkLoadedLevel", SendMessageOptions.DontRequireReceiver);
}

this is one major mind fuck thanks to c# being nearly useless, and javascript being well, javascript.

so i’m assuming we’re all working off of the same code, and in order to fix the problem you need to make the following changes:

[RPC]
public void LoadLevel(string level, int levelPrefix)
{
  StartCoroutine(loadLevel(level, levelPrefix));
}
	
private IEnumerator loadLevel (string level, int levelPrefix)
{
		
	showLobby = false;
    Debug.Log("Loading level " + level + " with prefix " + levelPrefix);
	lastLevelPrefix = levelPrefix;

	// There is no reason to send any more data over the network on the default channel,
	// because we are about to load the level, thus all those objects will get deleted anyway
	Network.SetSendingEnabled(0, false);	

	// We need to stop receiving because first the level must be loaded.
	// Once the level is loaded, RPC's and other state update attached to objects in the level are allowed to fire
	Network.isMessageQueueRunning = false;
		
	// All network views loaded from a level will get a prefix into their NetworkViewID.
	// This will prevent old updates from clients leaking into a newly created scene.
	Network.SetLevelPrefix(levelPrefix);
	Application.LoadLevelAdditive(level);
    yield return new WaitForEndOfFrame();
	yield return new WaitForEndOfFrame();
    Debug.Log("Loading complete");
		
  	

    Debug.Log("load level DONE");
	// Allow receiving data again
	Network.isMessageQueueRunning = true;
	// Now the level has been loaded and we can start sending out data
	Network.SetSendingEnabled(0, true);
		
	Debug.Log("sending load msg");
	// Notify our objects that the level and the network is ready
	foreach (GameObject go  in FindObjectsOfType(typeof(GameObject)) )
	{
			Debug.Log("sending load msg");
			go.SendMessage("OnNetworkLoadedLevel", SendMessageOptions.DontRequireReceiver);	
	}
}

so level additive works and i dont know exactly why, but you need to change your function to a non RPC with return type IEnumerator so that yield will work properly. and in order to call as a RPC, make a dummy function with return type void. and start a coroutine so yield can work its magic.

Meantime, I dont have my debugger with me now but I'll convert it to something like this. Does it look similar to yours?

public void LoadLevel (string level, int levelPrefix)
{
    // omitted code

    Application.LoadLevel(level);
    yield;
    yield;

    // Allow receiving data again
    Network.isMessageQueueRunning = true;
    // Now the level has been loaded and we can start sending out data
    Network.SetSendingEnabled(0, true);

    // Notify our objects that the level and the network is ready
    foreach (GameObject go in FindObjectsOfType(GameObject))
        go.SendMessage("OnNetworkLoadedLevel", SendMessageOptions.DontRequireReceiver); 
}