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\$
6
  • 1
    \$\begingroup\$ Can you show us your GetSprite method? Also, have you considered using the Unity Tilemap rather than instantiating thousands of GameObjects? You might find it's able to handle this more efficiently. \$\endgroup\$
    – DMGregory
    Commented Apr 5, 2018 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
    Commented Apr 5, 2018 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
    Commented Apr 5, 2018 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
    Commented Apr 5, 2018 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
    Commented Apr 6, 2018 at 1:33

1 Answer 1

2
\$\begingroup\$

It turns out the problem was not in this code at all, but in 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 \$O(n)\$ search, so creating \$n\$ objects results in an \$O(n^2)\$ slowdown.

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

\$\endgroup\$
9
  • \$\begingroup\$ Is O(n^2) right? Create n gameObjects, then iterate n gameObjects. I think its n+n, not n*n. So O(n) should be the time complexity. \$\endgroup\$
    – Evorlor
    Commented Dec 23, 2022 at 22:10
  • 1
    \$\begingroup\$ Every time an object is created the list of objects is searched, so N searches of a list of (at least) N objects. \$\endgroup\$
    – david.pfx
    Commented Dec 24, 2022 at 0:40
  • \$\begingroup\$ FWIW I just made the exact same mistake again, which reduced the frame rate from well over 100 to less than 2. And it's not easy to spot or diagnose. \$\endgroup\$
    – david.pfx
    Commented Dec 24, 2022 at 0:42
  • \$\begingroup\$ Ah, gotcha. Thanks. \$\endgroup\$
    – Evorlor
    Commented Dec 24, 2022 at 1:24
  • \$\begingroup\$ Would that not be O(n*log(n))? I know I'm being pedantic :-p \$\endgroup\$
    – Evorlor
    Commented Dec 24, 2022 at 2:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .