0

I have a Class that is failing when running in WebGL but it works in the UNITY IDE (5.6.1f1 Personal (Plus) Edition.) The code is 'trimmed' below, but yields the same characteristics (fails as a WebGL and runs w/ no issues in the UNITY IDE.) I'm pointing this to a service URL and get back a proper response when testing, but the Post actually never occurs when running from the WebGL and will crash when no response (not even an error) is received. I would like to get thoughts from the community (maybe I need to set a specific build parameter or modify the code implementation?) Helpful feedback would be much appreciated. Thank you.

-------------------- Wrapper and JSON Utility Classes ----------------

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class JsonTest : MonoBehaviour {

    JsonCommunicationManager jsonComm;

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }

    public void OnMouseDown()
    {

        var jsonCommunications = gameObject.AddComponent<JsonCommunicationManager>();
        string tempReturn = jsonCommunications.PostStartUpRequest("{\"userId\":1,\"id\":1}");
        Debug.Log("JSON RequestStartParms: Response :  " + tempReturn);

    }
}


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class JsonCommunicationManager : MonoBehaviour
{

    private WWW wwwForm;


    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }

    public string PostStartUpRequest(string JsonPostMessage)
    {

        Debug.Log("Inside PostMessage:");

        string JsonReturnMessage;

        StartCoroutine(PostWWWMessage(JsonPostMessage));

        bool boolResponse = false;

        do
        {
            Debug.Log("Checking for Response ");
            try
            {
                JsonReturnMessage = wwwForm.text;
                boolResponse = true;
            }
            catch
            {
                WaitForResponse();
                Debug.Log("Inside JsonPost Message:  WAIT");
            }
        } while (!boolResponse);

        JsonReturnMessage = wwwForm.text;

        Debug.Log("Inside JsonPost Message: Messgae Response Received: ");
        Debug.Log("Inside JsonPost Message: Messgae Response Data: " + JsonReturnMessage);
        Debug.Log("Inside JsonPost Message: Messgae Response Received: ");
        Debug.Log("Inside JsonPost Message: Messgae Response Error: " + wwwForm.error);
        Debug.Log("Inside JsonPost Message: Messgae Response Received: ");

        return JsonReturnMessage;
    }

    //private void PostWWWMessage(string JsonPostMessage) {
    private IEnumerator PostWWWMessage(string JsonPostMessage)
    {

        Debug.Log("Inside PostWWWMessage:");
        Dictionary<string, string> headers = new Dictionary<string, string>();
        headers.Add("Content-Type", "application/json");
        byte[] postData = System.Text.Encoding.ASCII.GetBytes(JsonPostMessage.ToCharArray());
        string fullyQualifiedURL = "https://jsonplaceholder.typicode.com/posts";

        Debug.Log("Inside PostWWWMessage: Posting Message: " + JsonPostMessage);
        print("Posting start up request to: " + fullyQualifiedURL);
        print("Post Data is:                " + postData);
        print("Post Header is:              " + headers);
        wwwForm = new WWW(fullyQualifiedURL, postData, headers);

        WaitForResponse();

        yield return null;

    }

    private IEnumerator WaitForResponse()
    {
        yield return new WaitForSeconds(1);
    }



}
RHooper
  • 1
  • 1

1 Answers1

3

This is what happens when you try to build a full program without understanding coroutine. I encourage you to create a new project, find a coroutine tutorial and study how it works. I think this is the best way for you to understand coroutine.

Things wrong in your code:

1.Trying to wait in a void function with a coroutine. This where you called WaitForResponse() inside the PostStartUpRequest function. This will not wait because PostStartUpRequest is a void function. Make PostStartUpRequest a IEnumerator function then wait with yield return WaitForResponse();.

2.Having a while loop in a void function that waits for another variable state to change in another function. while (!boolResponse); is not a good idea unless you are doing it from another Thread but you're not. This will freeze Unity since you are not giving other functions chance to run. You can fix this by adding yield return null; inside the while loop which waits for frame after each check. This allows other functions to run. You must change the PostStartUpRequest function to a IEnumerator function in order to do this.

do
{
    //Wait for a frame
    yield return null;
    ....
} while (!boolResponse);

The crash you get likely comes from here.

3.When you called the WaitForResponse(); function from the PostWWWMessage function to wait for 1 second, that shouldn't work because you are not yielding. You have to wait for the WaitForResponse() function to finish waiting. You do this by yield it.

That should be yield return WaitForResponse(); instead of WaitForResponse().

4.Not properly waiting for WWW request to finish. Webrequest depends on the Speed of the device and internet. Sometimes, it can take more than the second you are waiting. You have to yield the WWW request instead of wiating for 1 second.

//Make request
wwwForm = new WWW(fullyQualifiedURL, postData, headers);
//Wait for request to finish
yield return wwwForm;

//Now you can safely use it:
JsonReturnMessage = wwwForm.text;

5.Not checking for error before accessing the web request result.

You need to check for possible error before accessing the result otherwise, expect anything to happen such as receive null values from the server.

if (String.IsNullOrEmpty(wwwForm.error))
{
   //No Error. Access result
    JsonReturnMessage = wwwForm.text;
}else{
   //Error while making a request
   Debug.Log(wwwForm.error);
}

Finally, I can't tell why you have so many functions for a simple web request. Just use one function to do that.

private WWW wwwForm;

// Use this for initialization
void Start()
{
    StartCoroutine(PostWWWMessage("Test"));
}

//private void PostWWWMessage(string JsonPostMessage) {
public IEnumerator PostWWWMessage(string JsonPostMessage)
{

    Debug.Log("Inside PostWWWMessage:");
    Dictionary<string, string> headers = new Dictionary<string, string>();
    headers.Add("Content-Type", "application/json");
    byte[] postData = System.Text.Encoding.ASCII.GetBytes(JsonPostMessage.ToCharArray());
    string fullyQualifiedURL = "https://jsonplaceholder.typicode.com/posts";

    Debug.Log("Inside PostWWWMessage: Posting Message: " + JsonPostMessage);
    print("Posting start up request to: " + fullyQualifiedURL);
    print("Post Data is:                " + postData);
    print("Post Header is:              " + headers);
    wwwForm = new WWW(fullyQualifiedURL, postData, headers);
    //Wait for the request
    yield return wwwForm;

    string JsonReturnMessage;
    //Check for error
    if (String.IsNullOrEmpty(wwwForm.error))
    {
        //No Error. Access result
        JsonReturnMessage = wwwForm.text;
        Debug.Log("Received: " + JsonReturnMessage);
    }
    else
    {
        //Error while making a request
        Debug.Log(wwwForm.error);
    }
}
Programmer
  • 121,791
  • 22
  • 236
  • 328