问题分析:Unity是有限制其他线程调用引擎的API的,而LeanCloud的SDK在网络操作中都是异步操作,所以回调会有异常。
解决方案:参考ios和android中原生开发,添加了一个静态方法,通过缓存回调,并在Unity主线程中Update中读取回调并处理。
参考代码如下:Global.cs
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
public class Global : MonoBehaviour {
private static Queue<Action> watingActions = null;
private static Queue<Action> handlingActions = null;
[RuntimeInitializeOnLoadMethod]
static void OnRuntimeMethodLoad() {
GameObject global = new GameObject("Global");
DontDestroyOnLoad(global);
global.AddComponent<Global>();
global.hideFlags = HideFlags.HideInHierarchy;
}
void Awake()
{
watingActions = new Queue<Action>();
handlingActions = new Queue<Action>();
}
void Update()
{
if (handlingActions.Count == 0)
{
lock (watingActions)
{
if (watingActions.Count > 0)
{
Queue<Action> tmp = handlingActions;
handlingActions = watingActions;
watingActions = tmp;
}
}
}
else
{
while (handlingActions.Count > 0)
{
Action action = handlingActions.Dequeue();
action.Invoke();
}
}
}
public static void runOnMainThread(Action action) {
lock (watingActions) {
watingActions.Enqueue(action);
}
}
}
调用方法如下
AVUser.LogInAsync(username, password).ContinueWith((t) =>
{
if (t.IsFaulted || t.IsCanceled) {
string err = t.Exception.Message;
Debug.LogFormat("login failed: {0}", err);
} else {
Debug.LogFormat("login success: {0}", AVUser.CurrentUser.ObjectId);
Global.runOnMainThread(() =>
{
Debug.Log("ui log: " + t);
SceneManager.LoadScene("Menu");
});
}
});