我正在Unity 3D应用程序中工作,其中有2种方法通过使用Oauth连接到服务:一种检索令牌,另一种基于令牌从服务检索JSON输出。 JSON准备好后,我将在TextMesh上更改文本。一切都在TextMesh脚本的start方法中运行。像这样:
void Start()
{
string authToken = getAuthToken();
CustomerGroups data = getCustGroups(authToken);
TextMesh curText = (TextMesh)gameObject.GetComponent(typeof(TextMesh));
curText.text = data.value[0].Field1+ "-" + data.value[0].Field2;
}
奇怪的是,当我在Visual Studio中使用“附加到Unity”并在Unity播放器中运行GameObject时,此方法非常有用,但是当我在不调试的情况下运行它(如运行几个步骤)时,总会得到:
NullReferenceException: Object reference not set to an instance of an object
HelloWorldInteractive.getAuthToken () (at Assets/HelloWorldInteractive.cs:106)
HelloWorldInteractive.Start () (at Assets/HelloWorldInteractive.cs:15)
实际方法是:
public string getAuthToken()
{
string token = string.Empty;
Dictionary<string, string> content = new Dictionary<string, string>();
TokenClassName json = null;
content.Add("tenant_id", "https//...");
content.Add("grant_type", "client_credentials");
content.Add("client_id", "xxxx");
content.Add("client_secret", "xxxx");
content.Add("resource", "https://...");
UnityWebRequest www = UnityWebRequest.Post("https://login...", content);
//Send request
www.SendWebRequest();
if (!www.isNetworkError)
{
string resultContent = www.downloadHandler.text;
json = JsonUtility.FromJson<TokenClassName>(resultContent);
//Return result
token = json.access_token;
}
return token;
}
再次,如果我不调试它,它将失败,但是当我在运行它时进行调试时,它的效果很好。我假设它可能与在Start方法中执行它们有关...也许我需要在其他地方执行它?我只需要准备好JSON数据,就可以从一开始就更改TextMesh的值。
答案 0 :(得分:6)
您的问题称为“比赛条件”。
在调试时,您“足够慢”,因此您的 "classpath:templates/clientdocs/file1.xls"
很有可能会得到结果,直到您到达需要的代码部分为止。
未调试时:您不等待,直到网络请求完成。
因此,当方法到达行时,UnityWebRequest
仍将具有值www.downloadHandler.text;
null
我不知道json = JsonUtility.FromJson<TokenClassName>(resultContent);
对JsonUtility.FromJson
作为输入值有什么作用,但我猜错是该错误已经抛出,还是可能返回null
,所以下一行
null
尝试使用值token = json.access_token;
访问json
会引发异常。
您必须使用Coroutine和null
直到得到结果(请参阅UnityWebRequest.Post)。
我会使用类似的回调方法
yield
并将其与回调方法(如
)一起使用private IEnumerator getAuthToken(Action<string> onSuccess)
{
string token = string.Empty;
Dictionary<string, string> content = new Dictionary<string, string>();
TokenClassName json = null;
content.Add("tenant_id", "https//...");
content.Add("grant_type", "client_credentials");
content.Add("client_id", "xxxx");
content.Add("client_secret", "xxxx");
content.Add("resource", "https://...");
UnityWebRequest www = UnityWebRequest.Post("https://login...", content);
//Send request
// !! wait until request finishes
yield return www.SendWebRequest();
if (!www.isNetworkError && !www.isHttpError)
{
string resultContent = www.downloadHandler.text;
json = JsonUtility.FromJson<TokenClassName>(resultContent);
//Return result
token = json.access_token;
// this should only be done on success
// execute the callback
onSuccess?.Invoke(token);
}
else
{
Debug.LogErrorFormat(this, "Downlaod failed with: {0} - \"{1}\"", www.responseCode, www.error);
}
}
或作为lambda表达式
private Start()
{
StartCoroutine(getAuthToken(OnReceivedToken));
}
privtae void OnReceivedToken(string authToken)
{
CustomerGroups data = getCustGroups(authToken);
TextMesh curText = (TextMesh)gameObject.GetComponent(typeof(TextMesh));
curText.text = data.value[0].Field1+ "-" + data.value[0].Field2;
}