I’m working on a sprite-based game. The player’s avatar can perform various animations, each of which is represented on a sprite sheet. Each sprite sheet is on a separate texture and a separate material. The avatar has a quad, and I change the material assigned to that quad based on what animation should be playing at the moment.
(Yes, I know this is non-optimal for render performance, and I am aware of texture atlassing and existing sprite tools like 2D Toolkit. For various reasons, those options are not currently on the table for this specific project.)
Here’s the problem:
- Start Unity and load the project (it’s important that it’s a fresh start)
- Run the project in the editor
- Perform a given animation for the first time = significant hitch
- Perform the same animation any time thereafter = no hitch for that specific animation
- Once all animations have been performed once, there are no further hitches and performance is quite stable
Two curious things:
- Running the game the second and subsequent times in the same Unity editor session produces no hitches at all, at any time
- Standalone builds have no problems whatsoever, not even on first run
I had to add some custom profiling (using Profiler.BeginSample/EndSample calls) to narrow it down, and this code:
Profiler.BeginSample("SetAnimation (Change Material)");
renderer.material = (m_animation.material != null ? m_animation.material : m_defaultMaterial);
renderer.material.SetColor("_Color", Color.white);
Profiler.EndSample();
…results in the following in the profiler:
Player.Update (817.38 ms, self 0.09 ms)
SetAnimation (Change Material) (817.17 ms, self 0.12 ms)
Loading.ReadObject (817.05 ms, self 766.80 ms)
It appears that in the editor only Unity is loading the material and texture for each animation just-in-time, rather than doing this at the time the scene is loaded (either in editor mode or in play mode).
My understanding is that Unity will load all dependent assets at scene load time (barring the use of LoadLevelAsync, which is not the case here), where “dependent assets” means anything the scene refers to, and anything those things refer to, and on down the chain. In this case, all these textures should exist in the dependency chain like so:
- Scene
- GameStates manager instance (in the scene)
- ShellState prefab reference (instanced by GameStates)
- PlayState prefab instance (instanced by ShellState)
- Player prefab instance (instanced and owned by PlayState)
- Avatar prefab instance (instanced and owned by Player)
- Sprite prefab instance (instanced and owned by Avatar)
- Animation class instances (properties of Sprite, serialized non-MonoBehaviour data class)
- Material instance (property of each Animation)
- Material’s texture reference (set in the Material just like with any standard Material)
So am I just misinformed about how Unity loads assets? The behavior definitely appears to be different between editor and standalone. Is there something I should be doing to ensure these textures are loaded with the scene in the editor? (I mean, other than a gross hack where I loop through and assign each texture at startup to get them cached or whatever is really going on behind the scenes, here.)