Ok so I made a preliminary version, where I generate a Dictionary<string,int> with indexes in the spritelist, which gets Generated when you access GetSprite, if it's not there already.
private Dictionary
<string,
int> mSpriteIndexes
= new Dictionary
<string,
int>(); private bool mIndexesDirty = true;
//(...)
public UISpriteData GetSprite (string name)
{
if (mReplacement != null)
{
return mReplacement.GetSprite(name);
}
else if (!string.IsNullOrEmpty(name))
{
if (mSprites.Count == 0) Upgrade();
if (mIndexesDirty || mSpriteIndexes.Count != mSprites.Count) GenerateSpriteIndexes();
int index;
if (mSpriteIndexes.TryGetValue(name, out index))
{
return mSprites[index];
}
else
{
for (int i = 0, imax = mSprites.Count; i < imax; ++i)
{
UISpriteData s = mSprites[i];
// string.Equals doesn't seem to work with Flash export
if (!string.IsNullOrEmpty(s.name) && name == s.name)
return s;
}
}
}
return null;
}
(...)
void GenerateSpriteIndexes()
{
mSpriteIndexes.Clear();
for (int i = 0; i < mSprites.Count; i++)
{
var uiSpriteData = mSprites[i];
mSpriteIndexes.Add(uiSpriteData.name, i);
}
mIndexesDirty = false;
}
You'll notice that it's somewhat naieve, and you need to manually set mIndexesDirty if the content of the spriteList is changed, sorted or some such. It also incurs a higher cost the first time, as it has to do a run through of the sprite list to generate the dictionary. That however pales in comparison with the otherwise constant iteration of the old version.
test case
void Test1()
{
var sprite = GetComponent<UISprite>();
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000; i++)
{
sprite.spriteName = SPRITE_A;
sprite.GetAtlasSprite();
sprite.spriteName = SPRITE_B;
sprite.GetAtlasSprite();
}
sw.Stop();
Debug.Log("Time to switch: " + sw.Elapsed);
}
GetAtlasSprite triggers the actual getting of data, which otherwise would only be fired once per update, which would otherwise make it impossible to test without many, many different sprites that changes. You'd also have to have the stopwatch persist for all the time, polluting the results. Point being, the results might be exaggerated, but should be representative.
Results:
Tested with an atlas that has 323 sprites in it. (the higher, the worse for the old way)
For the first tests, the SPRITE_A and SPRITE_B where randomly selected (both number 73 and 74).
Test with 1.000 (x2) sprite changes shown in ticks (
http://msdn.microsoft.com/en-us/library/system.timespan.ticks.aspx)
List search - first run:
38.724, subsequent:
~33.000Dictionary lookup - First run:
6.613, subsequent:
~4.800Improvement: factor of ~6.
Test with 10.000 (x2) changes
List search - first run:
352.759, subsequent:
~340.000Dictionary lookup - First run:
48.725, subsequent:
~47.000Improvement: factor of ~7.
In the last test, I specifically chose the two last sprites in the list (322, 323) to show worst case (or bad case) scenario:
Test with 10.000 (x2) changes
List search - first run:
1.364.008, subsequent:
~1.350.000Dictionary lookup - First run:
45.522, subsequent:
~43.000Improvement: Factor of ~30.
So it does seem like the standard way gets significantly slower as the amount of sprites grow, ~300 sprites = factor 30, ~70 sprites = factor 7 suggests that +10 sprites adds a factor.
So, this treatise does suggest some merit in a dictionary wrapper for sprites.
