I'm doing a project on Unity Webgl and getting an error only when I build the project (in the editor it works fine). Basically I'm using a Jsonblob link to assign the parameters to a custom struct I made.
The error says: Could not parse response {object}. Exception has been thrown by the target of an invocation.
{object} being the json I'm using in the jsonblob website.
The struct I'm using looks like this:
public struct GameSettings
{
public String venueName { get; set; }
public Monitor[] monitors { get; set; }
public Flag[] flags { get; set; }
public InformationMonitor[] informationMonitors { private get; set; }
public Banner[] banners { get; set; }
private const int MAX_MONITOR_LENGHT = 4;
}
While the functions where I get the data and assign it look like this:
public GameSettings gameSettings;
public void Awake()
{
isRecovered = false;
GetData((response) => {
isRecovered = true;
gameSettings = response;
});
}
public async void GetData(System.Action<GameSettings> callback)
{
var url = jsonURL;
var httpClient = new HttpClient(new JsonSerializationOptions());
var result = await httpClient.Get<GameSettings>(url);
callback(result);
}
As the error says, it seems to have trouble parsing the object, although I dont really understand why that is and especially why is it happening when the project works properly in the editor, am I missing something?
CodePudding user response:
As WebGL doesn't support multi-threading nor async
the HttpClient
is not supported on WebGL at all (also see here).
You should rather use a UnityWebrequest.Get
and for the JSON deserialization either use the built-in JsonUtility
or Newtonsoft Json.NET
which comes as a Package and preinstalled in latest versions.
E.g. something like
// In order to use the built-in serializer your types need to be [Serializable]
[Serializable]
public struct GameSettings
{
private const int MAX_MONITOR_LENGHT = 4;
// Note that all nested types also need to be [Serializable]
// Also at least the built-in JsonUtility only supports fields by default, no properties
// so either make them all fields or use Newtonsoft
// or enforce serialization using the undocumented [field: SerializeField] for each property
public string venueName;
public Monitor[] monitors;
public Flag[] flags;
public InformationMonitor[] informationMonitors;
public Banner[] banners;
}
public GameSettings gameSettings;
public string jsonURL;
// Start can be a Coroutine, if it returns IEnumerator it is automatically
// statred as a Coroutine by Unity
private IEnumerator Start()
{
isRecovered = false;
// you can simply yield another IEnumerator
yield return GetData();
}
private IEnumerator GetData()
{
using(var www = UnityWebRequest.Get(jsonURL))
{
// Request and wait for the result
yield return www.SendWebRequest();
if(www.result != UnityWebRequest.Result.Success)
{
Debug.LogError($"failed due to \"{www.error}\"", this);
yield break;
}
// now this depends on how good your types are (de)serializable
// either the built-in way
gameSettings = JsonUtiltiy.FromJson<GameSettings>(www.downloadHandler.text);
// or directly using Newtonsoft
gameSettings = JsonConvert.DeserializeObject<GameSettings>(www.downloadHandler.text);
isRecovered = true;
}
}