Search Unity

[0.7.4] When instantiating a prefab, the Callback is called too late on Android

Discussion in 'Addressables' started by TobiasW, Apr 26, 2019.

  1. TobiasW

    TobiasW

    Joined:
    Jun 18, 2011
    Posts:
    91
    I'm using this code to instantiate a prefab and change some values once it's instantiated:

    Code (CSharp):
    1. gameObjectReference.Instantiate(spawnParent).Completed += delegate(AsyncOperationHandle<GameObject> operation)
    2. {
    3.    if (operation.Status != AsyncOperationStatus.Succeeded)
    4.    {
    5.        Debug.LogError("Couldn't instantiate GameObject");
    6.        return;
    7.    }
    8.  
    9.    var instance = operation.Result;
    10.    instance.GetComponent<RectTransform>().anchoredPosition = new Vector2(Random.value * 200 - 100, Random.value * 200 - 100);
    11.    instance.GetComponent<Text>().color = Color.HSVToRGB(Random.value, 1f, 1f);
    12. };
    13.  
    This is working fine in the editor, but when I build and execute it on Android, the prefab will first be rendered (white and at its default position) and only then (in the next frame, I presume) will the Completed callback set a new position and color.

    (And by the way, the same behaviour happens everywhere and always when using coroutines and async. It makes sense - once the coroutine has yielded, it will only continue in the next frame, even if the instance is created in the same frame, but this makes coroutines/async a bit useless in regards to Instantiate.)
     
    Last edited: Apr 27, 2019
    RecursiveFrog likes this.
  2. RecursiveFrog

    RecursiveFrog

    Joined:
    Mar 7, 2011
    Posts:
    350
    I feel like Instantiate May have only very limited uses. Regarding GameObjects, once you’ve loaded the asset all you have to do is use GameObject.Instantiate on the asset for a synchronous call.

    You can’t Instantiate addressable assets until they are loaded anyway, so I don’t see the value in using the system to Instantiate when you can do it yourself with less hassle.
     
    chanon81 likes this.
  3. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    Two good options, and one less good:
    1. do what @RecursiveFrog suggests of instantiating yourself. The catch here is that if you use addressables to instantiate into a scene, then close the scene, we'll decrement our ref-counts and unload the underlying content/bundles/whatever once appropriate. If you do a load through addressables, then instantiate yourself, you have to keep up with the load result to decrement the ref count once you are ready.
    2. Do what you are already doing, but set the default start location of the prefab somewhere it won't be seen.
    3. take a look at our sync demo to do some weird stuff with it: https://github.com/Unity-Technologies/Addressables-Sample
     
  4. TobiasW

    TobiasW

    Joined:
    Jun 18, 2011
    Posts:
    91
    Yeah, #1 is what I've already suggested to my client.

    What I mainly wanted to point out here is that the code above works differently in the editor and on Android. In the editor, it will always call Completed before rendering, on Android it will always call Completed after rendering.

    Ideally it would always call it before rendering everywhere. (Or at least be consistent, if a little useless.)