仅当未在Unity 3D播放器中调试时才出现NullReference错误

时间:2019-02-20 05:57:36

标签: json unity3d oauth-2.0 nullreferenceexception

我正在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的值。

1 个答案:

答案 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会引发异常。


您必须使用Coroutinenull直到得到结果(请参阅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;     
}