【问题标题】:Parse.com - How to make callback function in unity?Parse.com - 如何统一制作回调函数?
【发布时间】:2015-08-01 05:41:23
【问题描述】:

我是 Unity 新手,我不知道如何在 unity 中创建 callBack function。 现在我正在做的是查询以从parse.com 获取数据。当我设置禁用/启用任何gameobject 时,数据正在正确但在相同的功能中,然后我得到主线程的错误。确切的错误信息是:-

错误-

SetActive 只能从主线程调用。 加载场景时,构造函数和字段初始化程序将从加载线程中执行。 不要在构造函数或字段初始化程序中使用此函数,而是将初始化代码移至 Awake 或 Start 函数。

我用来获取数据的以下代码/函数。

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);
                }
            }
        });

    }

【问题讨论】:

    标签: c# multithreading parse-platform unity3d callback


    【解决方案1】:

    您不能从另一个线程调用统一函数。因此,如果您希望您的函数在主线程上运行,请执行以下步骤:

    1.在你的场景中创建一个游戏对象并添加一个这个脚本:

    公共类 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) 将您的协程操作添加到队列中,只要您想这样调用它:

    DoOnMainThread.ExecuteOnMainThread.Enqueue(() => { StartCoroutine(WaitAlertView4()); } );

    它将在主线程可以执行的下一次机会中执行,或者更确切地说,当游戏对象将调用它的更新方法时

    【讨论】:

      【解决方案2】:

      您无法从后台线程更新 UI。似乎 scoreapp42.instance.loadingwindow 指向一个 UI 对象,这就是您看到上述错误的原因。

      原来 System.Windows.Threading 命名空间属于用于 Windows Presentation Framework 的 WindowsBase 程序集。因此,使用 Dispatcher 的想法不适用于这种情况。解锁自己的唯一其他方法是不在后台线程中执行任何 UI 工作。而是等到后台线程成功完成,然后再做 UI 工作。

      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);
      }
      

      【讨论】:

      • 如何从主线程调用它或如何切换到主线程。请通过代码给出一些解释。
      • 你能尝试包括我在这里指定的代码 sn-p 吗? Dispatcher 基本上是在主线程上运行代码。在当前状态下,您的代码正在后台线程中运行所有内容。
      • 如何在添加 Dispatcher.Invoke(() => { scoreapp42.instance.loadingwindow.seActive(false); } 这一行代替 scoreapp42.instance.loadingwindow.seActive(false) ); 这然后我得到了很多错误。请帮助我
      • parth 我的脚本中没有调度程序选项,这是否意味着我需要在我的统一中添加任何库。我怎么能得到这个。如果我写 dispatcher.invoke 它会显示很多错误,例如 The name `Dispatcher' does not exist in the current context
      • 您不需要添加任何库。 Dispatcher 是 System.Windows.Threading 命名空间的一部分。基本上,调度程序是发送到线程以在该特定线程上执行函数的请求。你能把这个命名空间导入到你的文件中,看看 Dispatcher 是否被识别?
      猜你喜欢
      • 1970-01-01
      • 2020-09-25
      • 1970-01-01
      • 2019-11-05
      • 1970-01-01
      • 2013-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多