Hey, I need to load a json file to place GOs based on the data. Now, I need to do this Async since I'm using AR that's using the main thread. Here's my typical Stream reader. I'm not sure how to go about this. I know there's a async await function for .NET 4.5 and I'm using Unity 2019.2. Code (CSharp): private void PlaceObject() { Vector3 pos = placementPose.position; Quaternion rot = placementPose.rotation; ObjClass[] obj; using (StreamReader stream = new StreamReader(Application.persistentDataPath + "/objects.json")) { string json = stream.ReadToEnd(); obj = JsonHelper.FromJson<ObjClass>(json); //populate container = Instantiate(TankObjectReference.Instance.tankObjectDictionary["ObjectContainer"], pos, rot) as GameObject; foreach (ObjClass item in obj) { //Debug.Log("****objectID: "+item.objectID); if (item.objectID != "") { try { GameObject objID = TankObjectReference.Instance.tankObjectDictionary[item.objectID]; var p = item.pos; var r = item.rot; var scale = item.scale; var go = Instantiate(objID, container.transform) as GameObject; go.transform.localPosition = p; go.transform.localRotation = r; go.transform.localScale = scale; } catch { Debug.Log("obj doesn't exist"); } } } } }
I'm not the most knowledgeable in this topic but I can give one idea. You want to find the thing taking the most time and inject wait time between it to give the illusion of "async" while still relying on the main thread. As long as there is enough wait time and the waits are frequent enough you can "splice" operations fairly easily using IEnumerator. I typically use the XML serializer instead of JSON, so I don't know if this is possible: try to read per line instead of ReadToEnd. If you can do that you can inject wait time between line reading using "yield return new WaitForSeconds(.1f)" or some arbitrary number. Your foreach loop that is already there is an obvious candidate for injecting these waits, you can save a lot of lag time by processing your Instantiate calls individually. If you've never used IEnumerator before you basically just make that the return value of your function--private IEnumerator PlaceObject(). Then use StartCoroutine(PlaceObject()) to start it. When it's an IEnumerator it must yield return something at some point. At the end you can just put yield return null, and it'll also yield return when you inject the waits. Just remember that you can no longer guarantee your operation will be done in any specific amount of time, and the place where you called StartCoroutine will still run to the end even while the function is yielding.
If you just want the stream to be read async, this should be fairly trivial. If you need to entire function to be async, you need to move the code to a separate async function. Code (CSharp): private async Task PlaceObject() { ... string json = await stream.ReadToEndAsync(); ... }