Reputation: 531
I'm new to unity and I don't know how to make a callBack function
in unity.
Right now what I'm doing is that I make a query to get the data from parse.com
. Data is getting correctly but in the same function when I set disable/enable any gameobject
then I get the error of main thread. The exact error message is :-
ERROR-
SetActive can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
the following code/ function I use to get the data.
public void GetTop10ScoreClassic()
{
List<string> fbscores=new List<string>();
List<string> fbplayer=new List<string>();
int i = 0;
int rank = 0;
// Debug.Log (PlayerPrefs.GetString ("FBUserId"));
Debug.Log ("Classic top 10 1");
var query = ParseObject.GetQuery ("ClassicFacebookScore").OrderByDescending("score").Limit(10).WhereContainedIn("userId",FBLogin.friendIDsFromFB);
query.FindAsync().ContinueWith(t =>
{
Debug.Log ("Classic top 10 2");
comments = t.Result;
Debug.Log(t.Result);
foreach (var obj in comments) {
i++;
int score = obj.Get<int>("score");
Debug.Log(score);
string playerName = obj.Get<string>("playerName");
Debug.Log(playerName);
string playerId=obj.Get<string>("userId");
Debug.Log(playerId);
fbscores.Add(score.ToString());
fbplayer.Add(playerName);
if(playerId==userId)
{
rank=i;// to highlight the user's score
}
}
//enable the colliders
foreach (BoxCollider2D colliders in Userrankscore.instance.myColliders)
colliders.enabled = true;
FbLeaderboard.instance.NetworkError = false;
scoreapp42.instance.loadingwindow.SetActive (false);
//Pass the list of score;
App42Score.instance.list (fbscores,fbplayer,"fb",Convert.ToInt32(rank));
if(t.IsFaulted)
{
//enable the colliders
foreach (BoxCollider2D colliders in Userrankscore.instance.myColliders)
colliders.enabled = true;
if(FbLeaderboard.instance.NetworkError)
{
scoreapp42.instance.errorwindow.SetActive(true);
scoreapp42.instance.loadingwindow.SetActive (false);
Debug.LogError("Network Error");
}
foreach(var e in t.Exception.InnerExceptions) {
ParseException parseException = (ParseException) e;
Debug.Log("Error message " + parseException.Message);
Debug.Log("Error code: " + parseException.Code);
}
}
});
}
Upvotes: 2
Views: 2300
Reputation: 343
You cannot call unity functions from another thread. So if you want your function to run on main thread then do the following steps:
1.Create a gameobject in your scene and add a this script:
public class DoOnMainThread : MonoBehaviour {
public readonly static Queue<Action> ExecuteOnMainThread = new Queue<Action>();
public virtual void Update()
{
// dispatch stuff on main thread
while (ExecuteOnMainThread.Count > 0)
{
ExecuteOnMainThread.Dequeue().Invoke();
}
}
}
2) Add your coroutine action into the queue whenever you want to call it like this:
DoOnMainThread.ExecuteOnMainThread.Enqueue(() => { StartCoroutine(WaitAlertView4()); } );
it will be executed next opportunity the main thread can, or rather when the game object will call it's update method
Upvotes: 2
Reputation: 2130
You can't update UI from a background thread. It seems like scoreapp42.instance.loadingwindow is pointing to a UI object which is why you are seeing the error you described above.
It turns out System.Windows.Threading namespace belongs to the WindowsBase assembly which is used for Windows Presentation Framework. Thus the idea of using a Dispatcher is not applicable in this scenario. The only other way of unblocking yourself is to not do any UI work in the background thread. Instead wait till the background thread completes successfully, and then do the UI work.
var query = ...;
var backgroundWork = query.FindAsync().ContinueWith(t =>
{
...
//enable the colliders
foreach (BoxCollider2D colliders in Userrankscore.instance.myColliders)
colliders.enabled = true;
FbLeaderboard.instance.NetworkError = false;
//scoreapp42.instance.loadingwindow.SetActive(false);
//Pass the list of score;
App42Score.instance.list (fbscores,fbplayer,"fb",Convert.ToInt32(rank));
...
});
// wait till the background work has completed
backgroundWork.Wait();
if (backgroundWork.IsCompleted)
{
// now do any UI related work
scoreapp42.instance.loadingwindow.SetActive(false);
}
Upvotes: 0