0

I'm trying to procedurally generate tiles on the screen as soon as the level loads. This question pertains to making my algorithm as efficient as possible.

  • What I was doing before: In the Update() function (this section of Update() function is only being called ONCE when the game starts), I was simply instantiating the tile 12,000 times on the screen to create the entire map for the game. In the following code, x[i] and y[i] are the grid co-ordinate values that I'm incrementing in another function.

Cons: Level takes a longer time to load. Pros: Once the level is loaded, fps stays consistent and high.

            void Update()
            {
              if (loadThisSectionOnce = false)
              {
                  loadThisSectionOnce = true;
                  for (int i = 0; i <= 12000; i++)
                  {
                    tiles[i] = Instantiate(tile, new Vector3(x[i], y[i], transform.rotation) as GameObject;
                  }
              }
            }
  • What I am trying to now: I only want to have the tiles that are around the player get instantiated, and as the player roams around, the other tiles are instantiated henceforth so that as the game loads initially, not all the tiles are loaded at the same time (hence less loading time - more dynamic).

    void Update()
    {
        var distance = Vector2.Distance(new Vector2(x[i], y[i], PlayerPosition);
        if (distance < 20.0F)
        {                           
            for (int i = 0; i <= 12000; i++)
            {                                        
                tiles[i] = Instantiate(tile, new Vector3(x[i], y[i], transform.rotation) as GameObject;
            }
        }
    }

NOTE: This time there is no boolean variable to make sure that this section of the Update() function is called only ONCE, but it's being called every frame.

Pros: Yay! ONLY the tiles which are around the player are generated + level loading time is super fast. Cons: There is a FOR loop (iteration upto 12000!) being called every frame because of which the frames per second (fps) is very LOW while the game is running.

What do I need?: How do make my second attempt more efficient? Is there any way? I appreciate the help!

Daqs
  • 720
  • 3
  • 8
  • 28

2 Answers2

0

Call this a cop out answer, but if your tileable texture coordinates start at the same coordinates as your player, then couldn't you just go to those coordinates and the surrounding coordinates to whatever distance you want and not even iterate through the rest?

For example:

var distance = Vector2.Distance(new Vector2(x[world_coordinate], y[world_coordinate], PlayerPosition);
for (int i = int(distance-20); i>= int(distance-20) && i<=(distance+20) i++):
    tiles[i] = Instantiate(tile, new Vector3(x[i], y[i], transform.rotation) as GameObject;
        }

I'm not exactly sure how you are holding the tiles in your array so I'm not sure the code I wrote fits, but I hope you get the idea. Find the range for your tile array within the given radius around your player, in this case within 20 units and then iterate only through those tiles and render them. Sorry if my code isn't correct. I'm not proficient in neither javascript nor the unity library.

Orren Ravid
  • 560
  • 1
  • 6
  • 24
0

Instantiation takes a long time in Unity. Instead of instantiating tiles all the time, create an object pool.

  • Determine the amount of tiles you'll need around the character.
  • Create this amount of tiles at start time.
  • Take track of how long have the character travelled. You can easily do it in your character controller as a property with a public getter, like odometer, since it performs all the necessary calculations anyway. Your tile manager doesn't need to do any checks if the character hasn't travelled long enough distance since last check.
  • If the character needs new tiles around them, take them from the pool and place them there.
  • If the character doesn't need tiles anymore, return them back into the pool. And now, it's usually the tricky part — because before using object pools, a lot of your scripts attached to the world tile probably relied on usual Unity lifetime of the object for their logic. But you'll have to rewrite them in such a way that when you return the object to the pool, they completely reset their state.
Max Yankov
  • 12,551
  • 12
  • 67
  • 135