sam*_*uke 0 json nullreferenceexception unity-game-engine oauth-2.0
我在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;
}
Run Code Online (Sandbox Code Playgroud)
奇怪的是,当我在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)
Run Code Online (Sandbox Code Playgroud)
实际的方法是:
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;
}
Run Code Online (Sandbox Code Playgroud)
而且,如果我不调试它,它会失败,但是当我在运行它时进行调试时,它运行良好.我假设它可能与在Start方法中执行它们有关...也许我需要在其他地方执行它?我只需要准备好JSON数据,这样我就可以在开始时更改TextMesh的值.
你的问题被称为"竞争条件".
当你进行调试时,你"足够慢",所以你UnityWebRequest很可能会得到一个结果,直到你找到需要它的部分代码.
虽然没有调试:你没有等到webrequest完成.
所以当方法到达该行时www.downloadHandler.text;仍然具有该值null
json = JsonUtility.FromJson<TokenClassName>(resultContent);
Run Code Online (Sandbox Code Playgroud)
我不知道exctaly JsonUtility.FromJson对于null输入值有什么作用,但我猜测错误已经在那里抛出或者它可能会返回null所以下一行
token = json.access_token;
Run Code Online (Sandbox Code Playgroud)
尝试json使用该值访问null是抛出异常.
您必须使用Coroutine,yield直到获得结果(请参阅UnityWebRequest.Post).
我会使用像这样的回调方法
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);
}
}
Run Code Online (Sandbox Code Playgroud)
并使用像回调方法一样使用它
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;
}
Run Code Online (Sandbox Code Playgroud)
或作为lambda表达式
private Start()
{
StartCoroutine(getAuthToken(
(authToken) =>
{
CustomerGroups data = getCustGroups(authToken);
TextMesh curText = (TextMesh)gameObject.GetComponent(typeof(TextMesh));
curText.text = data.value[0].Field1+ "-" + data.value[0].Field2;
}
));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
69 次 |
| 最近记录: |