In my latest Unity3D app I dynamically load assets from the Resources folder and place them in the world after the initial scene load. These assets use new materials and textures that must be uploaded to the GPU. I thought I was being slick by caching prefabs to prevent a loading hiccup when I needed to instantiate. However, that’s only part of the problem. After placing the object in the scene, my game would freeze up for a frame or two when the newly created object first became visible. The profiler showed this spike attributed to a function called AwakeFromLoad.
It turns out Unity3D does not load the GPU with your new object’s assets until it’s first visible. Apparently, this is what AwakeFromLoad does. This is an optimization technique presumably to prevent thrashing on the GPU by loaded assets that won’t be visible immediately. The downside is you’ll see a pause as Unity3D uploads data to the GPU. From what I can tell, this can even mean compiling the shader if it hasn’t been used in the scene yet.
Unity doesn’t provide a function to force the GPU to load assets. From looking at Unity forum threads, the most common solution is to put up a loading screen and show newly instantiated assets to the main camera for a frame to force a GPU load. Once all the assets have been made visible, the loading screen is dropped.
Putting up a loading screen just seemed like a huge pain in the ass, not to mention an ugly hack. So, I came up with a solution using Unity Pro’s RenderTexture and a second camera. Now, my game scene has two cameras: the Main Camera and a disabled secondary camera with a tiny 32×32 RenderTexture as its target. Whenever I instantiate a new asset in the world, I position the second camera in front of it and render a frame to this texture. This forced rendering does the trick of uploading all necessary data to the GPU. Yes, there still is a loading spike, but you decide when it’s going to happen and you don’t have to reposition your object in view of the main camera for a frame.
I put this in a behavior called AssetGPULoader, you can grab it here. It only works with Unity3D Pro as it needs RenderTexture. As far as I can tell, this does the trick. It has removed my unpredictable performance spikes. For an alternative solution, I also found this technique in the Unity forums.