1
\$\begingroup\$

My 2D Unity game has tiles and layers. It creates one game object per tile, anywhere from 100 to 10,000. To create 3,000 game objects takes 68 msec, which is just fine.

But setting up the sprite and location takes 5,000 msec, or nearly 2 msec per sprite. This is a problem. Here is the code for setting up each tile.

   var sprite = _main.GetSprite(LevelIndex);  // pre-computed table of sprites
   _renderer.sprite = sprite;  // the sprite renderer for the tile
   if (sprite != null) {
     var cursize = _renderer.sprite.bounds.size;
     var scale = Math.Max(Size.x / cursize.x, Size.y / cursize.y);
     transform.localScale = new Vector3(scale, scale, 0);
   }

How can that code take 2 msec? What's going on?

The sprite size is 80x80. Is this a problem?

Once it's all set up it renders at 100 fps easily. So why is the setup so slow, and what can I do about it?


Yes, I considered using a TileMap. It's not easy to see how to create one in fully procedural code, but at the heart of it is the Tile class, which has a GameObject and a Sprite. If I implement my own Tile class it's going to have code that looks a lot like the above, and (after a lot of work) most likely perform exactly the same.

Since Tile and TileMap are just layers over standard Unity infrastructure, then if they do have a way to perform much faster, I should be able to apply the same technique to my situation and get the same performance.

\$\endgroup\$
  • 1
    \$\begingroup\$ Can you show us your GetSprite method? Also, have you considered using the Unity Tilemap rather than instantiating thousands of GaneObjects? You might find it's able to handle this more efficiently. \$\endgroup\$ – DMGregory Apr 5 '18 at 13:37
  • \$\begingroup\$ The GetSprite functions is essentially free -- it's a single Dictionary lookup of pre-computed sprites. And no, I have not been able to create a Tilemap in code but in any case (a) why is this way so slow and (b) would a Tile in a TIlemap that uses a gameobject and sprite be any faster? \$\endgroup\$ – david.pfx Apr 5 '18 at 14:21
  • 1
    \$\begingroup\$ Did you run the profiler? Are you certain that the bottleneck is that chunk of code, or is it rather the fact that you lookup 5000 times in a dictionary? \$\endgroup\$ – Vaillancourt Apr 5 '18 at 14:38
  • \$\begingroup\$ I would suspect that setting the _renderer.sprite property does far more than just a simple setter. But without proper profiling, this is just a wild guess. \$\endgroup\$ – Philipp Apr 5 '18 at 14:53
  • \$\begingroup\$ @AlexandreVaillancourt: yes, I ran both the profiler and my own timing code. Actually LevelIndex is an integer and it's an array index, not even a Dictionary (oops). That definitely isn't it. \$\endgroup\$ – david.pfx Apr 6 '18 at 1:33
2
\$\begingroup\$

Turns out the problem was not in this code at all, but some code in the instantiated game object:

void Start() {
  _mainx = FindObjectOfType<MainController>();
}

For a few objects this is cheap enough, but this API call does an On search, so creating N objects results in an On^2 slowdown.

Take away this code and Unity can happily instantiate and render thousands of simple game objects with no noticeable time delay.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.