I have been experiencing some longer than expected load times on ios.
I have found several other threads on the same issues.
My addressables use case is the simplest. The addressable bundles are packed with the build locally.
No downloads.
I have setup some test to look at different ways of loading.
Initially on my PC. This is a high end PC, M2 SSD, i9, 3080. 64gb ram.
Unity 2021.1.25f1, addressable 1.18.19
It’s a simple test.
- Load scene (additive) with model prefab in it.
- Load scene (additive) async with model prefab in it.
- Load addressable of the same model prefab as in the scenes.
Here are the results.
~250 ms Sync Scene
~259.05 ms Async Scene
~977 ms Addressable
I ran this a few times in a windows Il2PP build.
My earlier tests were showing the a huge difference in the sync and non sync.
But when I added a frame delay they are now coming about about the same.
I think when the sync loadscene call finishes unity has not actually loaded the assets to render them yet.
And the prefab has some other scripts on it that could be doing work on the following frame.
This was really noticeable on my iphone test. Sync showed a few ms to load but then a bit later model appeared. Adding the frame to all tests makes the time reported and model appearance match up.
The extra frame increased the sync loadscene test but had no real affect on the others.
When I deployed this same setup to iphone12 and a iphone 7+.
The 12 sync loadscene is about 2x as fast about 250ms vs 500ms.
But the async scene and the addressable are in the same range.
About 5s and about 8s. ± .5s
I was a little surprised by this. But maybe while the CPUs are faster the flash read times maybe similar.
But in either case the async is longer and the addressable is considerably longer.
I was thinking about possibly using Resources.LoadAsync and testing or possibly asset bundles.
But I thought Resources.Load was deprecated even though I think the LoadAsync maybe newer.
And I thought addressables loaded the asset bundle under the hood anyways so not sure I will get an speed up there.
Unless the slowdown comes from the async aspect and i could load the asset bundle synchronously.
I may try it see what happens.
Otherwise for now i think i am stuck just loading everything and hoping to not run out of memory.
Initially that will be ok. But as our game grows this may become a problem to let you select from lots of characters and having to have them all in memory.
I can probably submit a bug with a paired down project if that would be useful.
The code for the test is as follows if anyone wants to try it.
public class TestController : MonoBehaviour
{
[SerializeField]
private Button _LoadSceneSync;
[SerializeField]
private Button _LoadSceneAsync;
[SerializeField]
private Button _LoadAddressable;
[SerializeField]
private AssetReferenceGameObject _Fighter;
[SerializeField]
private TMPro.TextMeshProUGUI _Text;
// Start is called before the first frame update
IEnumerator Start()
{
_LoadAddressable.onClick.AddListener(LoadAddressable);
_LoadSceneSync.onClick.AddListener(LoadSceneSync);
_LoadSceneAsync.onClick.AddListener(LoadSceneASync);
AsyncOperationHandle<IResourceLocator> handle = Addressables.InitializeAsync();
yield return handle;
}
private void LoadSceneSync()
{
IEnumerator LoadSceneCo()
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
UnityEngine.SceneManagement.SceneManager.LoadScene("FighterScene", UnityEngine.SceneManagement.LoadSceneMode.Additive);
yield return 0;
sw.Stop();
_Text.text = string.Format("Load Scene Sync: {0}", sw.Elapsed.TotalMilliseconds);
Debug.Log(_Text.text);
}
StartCoroutine(LoadSceneCo());
}
private void LoadSceneASync()
{
IEnumerator LoadSceneCo()
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
yield return UnityEngine.SceneManagement.SceneManager.LoadSceneAsync("FighterScene", UnityEngine.SceneManagement.LoadSceneMode.Additive);
yield return 0;
sw.Stop();
_Text.text = string.Format("Load Scene Async: {0}", sw.Elapsed.TotalMilliseconds);
Debug.Log(_Text.text);
}
StartCoroutine(LoadSceneCo());
}
private void LoadAddressable()
{
IEnumerator LoadSceneCo()
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
yield return _Fighter.InstantiateAsync();
yield return 0;
sw.Stop();
_Text.text = string.Format("Load Addressable: {0}", sw.Elapsed.TotalMilliseconds);
Debug.Log(_Text.text);
}
StartCoroutine(LoadSceneCo());
}
