- Home /
The question is answered, right answer was accepted
Failed to Wait on a Semaphore
I have written a script which downloads the assetBundle from local path in which I am Using WWW class to convert a txt file to string and again using WWW class to download the assetBundle. This Setup works fine in Android Build. However when I try to Build this for Iphone the assetBundle Instantiates once but after destroying it and downloading it again the app freezes and I get this Error "Failed to Wait on a Semaphore". The script I am using is
function StartDownload () {
www = new WWW ("file:///mnt/sdcard/AssetBundles/selected.txt");
yield www;
url = www.text;
if (Application.platform==RuntimePlatform.Android)
download = new WWW ("file:///mnt/sdcard/AssetBundles/"+url);
yield download;
assetBundle = download.assetBundle;
if (assetBundle != null)
{
var go : GameObject = assetBundle.mainAsset;
goParent = GameObject.Find("Parent");
if (go != null)
{
instanced = Instantiate(go);
instanced.transform.parent = goParent.transform;
instanced.transform.localPosition = new Vector3(0,0.125,0);
}
else
Debug.Log("Couldnt load resource");
}
else
{
Debug.Log("Couldnt load resource");
}
}
function OnGUI()
{
if (download == null)
{
dataset = GetComponent("DefaultTrackableEventHandler");
if (GUI.Button(Rect(40,20,200,40),"Download",customGUIstyledownload.button))
{
StartDownload();
}
else
{
if (download.error == null)
{
var progress = parseInt(download.progress * 100);
GUILayout.Label(progress + "%");
if (download.isDone && GUI.Button(Rect(40,20,200,40),"Unload Resource",customGUIstyledownload.button))
{
Destroy(instanced);
download.Dispose();
download = null;
// Unload the whole asset bundles and any loaded assets
assetBundle.Unload (true);
assetBundle = null;
}
if(dataset.track==false)
{
instanced.SetActiveRecursively(false);
instanced.active=false;
}
if(dataset.track==true)
{
instanced.SetActiveRecursively(true);
instanced.active=true;
}
}
else
{
GUILayout.Label(download.error);
}
}
}
What I think is that for Iphone the assetBundle is not destroying properly before its loaded again thus crashing the app .Or another possibility is that my use of two yields after one another is causing the problem. Any solutions or insights could be useful.
P.S- Please keep in mind that the script works fine for the first time the AssetBundle is Instantiated plus this script works fine on the Android.
Edit : - The Script I posted is for android but i changed it according to Iphone and please do keep in mind that this script runs successfully for the first time in Iphone.The problem might be in the way the Iphone manages its memory.
The exact error I am getting is
"Failed to wait for a Semaphore(errno:15)"
Answer by udaanparvaz · Aug 09, 2012 at 08:49 AM
I rectified it finally by stripping off the extra instructions that were in the OnGUI function. The Unity engine's OnGUI is really expensive as it is called two times per frame. When I ran the profiler I caught the culprit. The reason this was code was running on android might be simple enough. I was testing this on Sony Xperia S which has 1.5 GHz Dual-Core. For Iphone this same code was heavy. Quite a refreshing learning curve for a beginner programmer like me.
So the lesson to learn is Only call needed functions in OnGUI if you're developing for smartphones.
P.S:- This is my 3rd question that I am answering myself.What's wrong guys? Am I asking the wrong questions ?
$$anonymous$$aybe you could give your questions a little more love. Formatting the code sections will make it easier readable and have more eyes read through your question. :)
thanks for the feedback.I pasted the code in the code sample...what else is required?
select the code and hit the code sample formatting button (1's and 0's).
Note that you may want to "show" or "highlight" where in your code is your problem. When looking at a glance, it's really hard to differentiate what specific line(s) of code you are having problems with.
Answer by Bunny83 · May 25, 2015 at 01:46 AM
Since the question got already bumped by demented_hedgehog i fixed the formatting of the code and have applied some proper indention. This script won't compile in it's current state since there's one closing bracket missing (most likely line 38).
Now to the actual question / problem. This script has actually tons of problems / possible problems.
Line 4: No error checking if the download was successful.
Line 6 / 7: A download is only created when the platform is Android but it's still passed to yield which makes no sense.
Line 5 - 7: Storing a WWW instance in an instance variable and maybe reuse it can be dangerous. For example you can't yield a WWW object two times. This could actually be the problem in some way. Since the error involves a semaphore, it's probably something in the loading thread of the WWW object.
Line 8: again no error checking if the download actually was successful. Furthermore since the creation of the "download" is in a conditional statement it could even by null at this point.
Line 33: Bad style and could cause problems depending on how the variable is actually declared.
Line 38: As mentioned above there's probably a "}" missing before the else
Line 53-62: That's a quite bad style. The two lines in the if-statements are actually always executed. Those 10 lines could be replaced by 2.
Here's the simplified version that does the same as the 10 lines and is much more readable:
instanced.SetActiveRecursively(dataset.track);
instanced.active = dataset.track;
Follow this Question
Related Questions
best way to show iphone purchased assets 0 Answers
WWW.LoadFromCacheOrDownload not working 1 Answer
Assetbundle can't load in IPhone 1 Answer
what is the faile reason? the model's or my codes'? 0 Answers
Smooth Synchronized HD Video Playback 0 Answers