Server Side Highscores Crashing Web Player

Hello all and good evening wherever you all are coding tonight…

I have been working adapting our beloved Server Side Highscores wiki script:
http://unifycommunity.com/wiki/index.php?title=Server_Side_Highscores
and crafting that to my own purposes and having a great time learning perhaps the DRYEST programming language I have every experienced. No wonder we prefer Game Development to Data base work… euch…

But I may be alienating the very people whose help I seek… Darn. I hate being me sometimes.

To get to the meat of the matter: The scripts WORK!!! I set up my MySQL database with no prior experience, and am able to save and load what I need to and re-load it, modify it, and re-save it!

… But ONLY in the Unity Editor… In the web browser of my build it FREEZES up and I have to force-quit my browser. The task manager shows Firefox (and Unity inside it) using up more and more memory and maximum processor power like I’m in an endless loop!

Help!

In another thread Andeeeee put up a link to Unity doc’s web player debugging log here:
http://unity3d.com/support/documentation/Manual/Web%20Player%20Debugging.html
Any ideas about where that info is on Windows 7??

Sure you respect the requirements for the webplayer security sandbox as layed out in the webplayer security sandbox in unity 3 manual so you aren’t trashing yourself by trying and trying and trying allocating new data and alike thats never going away cause the coroutines don’t succeed

as for the file: c:\appdata\local low\unity I think, if you set the user temp folder to another place like I did, then its that new temp folder/unity

Whoa. Lots of font juggling there.

dreamora is probably on the right track. You’ll find more about the webplayer sandbox here: http://unity3d.com/support/documentation/Manual/Security%20Sandbox.html

I went to the link suggested by Dreamora and pasted the following in a text editor:

<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>

saved it as crossdomain.xml and put it in the root folder of the domain with the PHP and MySQL files. It is the same domain where the Unity file is, but I didn’t see that file there before.

Nothing changed. Attempting to load from that site froze the browser, and, yes, it was eating up more and more memory, really fast, about 25 megabytes per second.

That’s supporting the case that Dreamora is correct when he says “Sure you respect the requirements for the webplayer security sandbox as layed out in the webplayer security sandbox in unity 3 manual so you aren’t trashing yourself by trying and trying and trying allocating new data and alike thats never going away cause the coroutines don’t succeed.” But I don’t know what to do about that yet.

More information:

  1. the last lines of the web player log were:

web: sucessfully initialized
110223 09:53:06 loader: start ok
web: parent window change: 905aa 900x600
110223 09:53:32 Times: download 0.7 load 32.1
Platform assembly: C:\Documents and Settings\Vimalakirti\Local Settings\Application Data\Unity\WebPlayer\player\3.x.x\Data\lib\UnityEngine.dll (this message is harmless)
Non platform assembly: data-22266FB8 (this message is harmless)
Non platform assembly: data-222795C0 (this message is harmless)
Initializing (RawInput).

Input initialized.

desktop: 1680x1050 60Hz; virtual: 1680x1050 at 0,0
Platform assembly: C:\Documents and Settings\Vimalakirti\Local Settings\Application Data\Unity\WebPlayer\player\3.x.x\Data\lib\CrossDomainPolicyParser.dll (this message is harmless)

  1. The code where I’m trying to load and using a Yield function are:
	IEnumerator SleepSecs (float secs) {
		yield return new WaitForSeconds(secs);
	}
	
	public string GetBarns(string userName)
	{
		barnData = null;

		
		string barns_url = displaybarnUrl + "userName=" + WWW.EscapeURL(userName);
		
	    WWW hs_get = new WWW(barns_url);
		
		float stop = Time.time + 10.0f;
		while ((!hs_get.isDone)  (stop > Time.time)) 
		{
			StartCoroutine(SleepSecs(1));
		}
	    if(hs_get.error != null) 
		{
	        print("There was an error getting the barn: " + hs_get.error);
	    }
		else 
		{
	    	barnData = hs_get.data;
	    }
		return barnData;
	}

I would think that while(… (stop > Time.time)) would limit how long the thing would try to load for, but apparently it’s not. I have waited more than ten seconds and it keeps running, frozen, eating up massive gobs of memory.

Thanks again for your help with this.

Well, there’s your problem :wink:

Indeed that while loop is what’s locking everything up and accumulating memory.

Effectively what you’re doing in there is:

  1. Make sure the main loop of Unity does not gain any updates till after your while condition is false.
    Unfortunately (stop > Time.time) will never evaluate to false though, since Time.time is updated each frame - not during a frame. And since your loop is locking up the main thread, you never get to the next frame.

  2. Spawn a new coroutine each iteration of your loop, as long as the loop is running (which as established above is forever).
    StartCoroutine creates a new coroutine run for the given call, but does not affect the execution context from which it is called. The result is that with each iteration, you spawn yet another coroutine thread which allocates more resources.

Here is one way of achieving what you are going for:

public delegate void ResultHandler (string result);

public IEnumerator GetBarns (string userName, ResultHandler handler)
{
	barnData = null;

	string barns_url = displaybarnUrl + "userName=" + WWW.EscapeURL(userName);
	
    WWW hs_get = new WWW(barns_url);
	
	float stop = Time.timeSinceLevelLoad + 10.0f;
	while (!hs_get.isDone  stop > Time.timeSinceLevelLoad)
	{
		yield return new WaitForSeconds (1);
	}
	
    if (hs_get.error != null) 
	{
        Debug.Log ("There was an error getting the barn: " + hs_get.error);
    }
	else 
	{
    	barnData = hs_get.data;
    }

	handler (barnData);
}

With this changed setup, you would have to call the GetBarns method like this:

// ...
StartCoroutine (GetBarns (userName, OnBarnsLoaded))
// ...

void OnBarnsLoaded (string barnsData)
{
	// ...
}

DISCLAIMER: Untested code, watch out for typos.

Emil,

Once again, thank you so much for you time and energy. I took some time to read up on exactly what IEnumerator and delegate are in C# and have come out much richer for the experience. I’ll do some reading on Coroutines this afternoon or maybe tomorrow. Putting up this build for my client has been really difficult. I had to learn PHP and MySQL and the WWW class from scratch for this, so I think I’ll take the day off.

Your help is always such an inspiration.
Thank you!