Asynchronous object instantiation

I have been using Unity professionally since 2011 and in every project, I encounter the problem that Unity’s async functionality is not fully asynchronous. I raised this issue many years ago without any resolution and today I would like to bring it up again, hoping that you will consider my feedback this time.

In every project I have worked on, it is necessary that at some point during the gameplay, the game needs to load and instantiate new content. There are many cases where you can’t create and pool every object you’d need at game start. Working around this issue is a tremendous time sink and often not even possible.

The Addressables API implements a lot of async operations, but only a portion of the operations are executed asynchronously:

https://docs.unity3d.com/Packages/com.unity.addressables@2.0/api/UnityEngine.AddressableAssets.Addressables.InstantiateAsync.htm

The Instantiate blocking the main thread is a severe issue and I would like to ask if you can change it.

I understand that Unity’s API is mostly not multi-threading safe, but according to the profiler, object instantiation is split into three parts: Instantiate.Copy, Instantiate.Produce, and Instantiate.Awake.

I believe user code does not run during Copy and Produce, which makes me wonder if you can run these two methods on another thread and only run Awake on the main thread.

Having the Copy and Produce calls not block the main thread would greatly improve the situation.

PS: I would also like to mention that I’m not asking for the perfect solution or a new system. I’m asking to improve what is already there and where I would benefit “immediately”. Perhaps this would be a good first step to improve the Instantiate situation.

9 Likes

You mean that various systems within Unity (like the addressables API mentioned in your post) would use the Object.InstantiateAsync (added in 2022.3+)? Yeah that would be cool.

7 Likes

I didn’t know Unity had added InstantiateAsync; that’s a true game-changer and a great addition! It certainly would be enormously useful for Addressables to make use of this asynchronous Instantiate API.

Can someone in Unity poke the Addressables team and ask if they can make this change, pretty please?

2 Likes

Just load adressable by key/label and instantiate manually.

Seems the people that did the InstantiateAsync feature were all fired: https://twitter.com/_jura_z_/status/1758703011453608298

It seems like addressables is the use case they had in mind when they made it, but who knows if there is anyone left that knows how and is willing to implement this.

12 Likes

@davidla_unity Sorry for the ping. Can you please ask the Addressables team to use the recently added Object.InstantiateAsync method in Addressables.InstantiateAsync?

7 Likes

I saw this thread, got excited, and tried Object.InstantiateAsync()… Unfortunately it still seems quite slow.

This prefab has ~1000 prefabs nested inside of it. The schedule takes ~11ms, then the next frame the awakes/instantiate stuff adds up to another ~10ms.

It’s great that this 20ms got split over two frames… but, why is the first 11ms on the main thread?!
This is on Unity 2022.3.21f1

1 Like

It’s unfortunate, the Object.InstantiateAsync is basically useless for me because it doesn’t accept scale. Like if you need to scatter objects over a scene by rapidly spawning them, chances are random scale comes into play - and if you need scale you’ll still need to go and touch all those objects after spawning them, making it take longer than if you just spawned them the old way. Like, isn’t this an incredibly obvious omission or is it just me?

Of course, the chance of this getting addressed in the next 5 years is basically 0.

4 Likes

Well that is sad… It’s almost like Unity is trying to shoot themselves in the foot again and again…
They’re creating quite the track record of failures.

I think InstantiateAsync is quite the addition. Though there were already some bugs with this new API related to UI (uGUI). There was some other thread about this. Hopefully others can fix those issues.
instantiateInWorldSpace is missing too. Scale would’ve been a nice addition.

Maybe we should just get a jbooth issue tracker pinned on the forum somewhere lol… that has all the issues you’ve found and would like fixes and improvements… I think we can all agree that your assets should be built in and I’m sure we all get tired of finding out things could be better if Unity just did this or that with the source instead of hacky workarounds and compromises on the asset side of things.

1 Like

I agree with you, it’s weird that scale is missing. It should really accept a NativeArray and it’d cover most use cases, I think. But, for now, I think you could probably work around this by using a job with a TransformAccessArray.

how does one learn this power?
seriously… I have tried

Just use the LoadAssetAsync and in the completed event keep the reference to the game object and use InstantiateAsync yourself.
You use it as a prefab asset that way. When you’re done using it, release the asset again.

1 Like

By writing your own asset bundle manager. It’s surprisingly easy! Addressables is comedically horrible, so we’ve been rolling our own solution for years without any issues.

6 Likes

Has the feedback from this thread made its way to the Unity offices?

1 Like

9795708--1405758--upload_2024-4-25_20-7-26.png

21 Likes

Reposting here too, for visibility.

Turns out this new API has a really bad memory leak, very unfortunate.

3 Likes

This won’t solve the async load/copy part but About the awake part of the instantiation:
we usually disable the whole object hierarchy at build time and enable them from top to bottom while measuring the time it takes to enable them at each step, yielding to next frame if goes over budget (e.g. 5ms). Another trick is to see what other assets these objects use, put them in separate asset bundles and load them beforehand because Unity loads them only on the first frame they get visible causing hiccups.

LoadAssetAsync gives more stutter than instantiation itself :slight_smile:

Also, it looks like the function overload that accepts a position, rotation, and parent just throws the parent parameter away and passes in null instead (at least on 2022.3.21f1)