2
votes

Firstly, I'm new to Unity and I'm currently learning c#, please be gentle!

As a project, I'd like to create a simple 3d platform game. The idea being the player starts on a square tile, which is the game platform playing area. They explore different elements on this tile by moving around.

The perspective is 3rd person, so the player is looking down on the action. As they approach the edge of the tile Unity recognises this and adds another tile to the existing one, basically doubling the playing area.

As the player moves around further to the tiles edge, other tiles are added, increasing the discovered areas each time.

My thinking to achieve this would be to have 5 tile game objects, that have different elements like trees already built on them. The question is what is the best way to achieve this.

Would it be to build the complete level with all tiles and then using code restrict how far ahead the player can see, basically to the width and length of the tiles.

Or would it be better to trigger a new tile to appear as the player approaches the edge of the current tile.

Thought, links to example code that I could recycle would be very handy.

Thank you.

1
Very interesting idea. I think the second approach (procedurally generate next tile) would be more memory-efficient. Easy solution would be to put some trigger colliders at the edges of each tile that, when triggered, create a new tile at appropriate location.AVAVT

1 Answers

2
votes

The question is primarily opinion based, but here is some advise:

There is no right way to make a game in unity. The correctness is mainly focused on performance; memory and processing.

There are two approaches here:

    • condition: Your world is endless (or very large) and player moves very slowly over time (say each tile takes more than a second to traverse).
    • solution: Do not instantiate everything at start, instead when player reaches the edge of a tile look for the next tile in your level structure to retrieve its data and then instantiate its objects.
    • condition: Your world is not very large (say it has less than overall 10K objects) OR player can move fast (as in Age of Empires game).
    • solution: Instantiate everything in loading phase and deactivate the game objects as they are being instantiated so that nothing is getting processed at the start of the game. In this case the level structure is a collection of game objects where you activate or deactivate them.

Hints:

  1. Pooling is a good practice when it comes to repetitive objects. Pool is basically an empty game object with a script, and many many deactivated children.

    • e.g. If you have 1K trees of the same kind you better have a tree pool. Create a game object named tree pool, add a pool script to it and make that script generate 1K deactivated tree game objects in the loading phase. Then whenever your level generator needs a new tree just fetch a tree from tree pool and activate and reposition it. Make sure you clean up the pool after the game ends to prevent memory leak.
    • you can implement the pool as you like to provide object variations for a specific pool.
  2. Instantiation in run-time is costly especially in mobile devices. Whenever you need to instantiate several game objects at once consider using a coroutine to prevent lag or freeze (this applies to loading phase too).

e.g.

IEnumerable CreateObjects(Data[] data)
{
    foreach(var e in data)
    {
        Instantiate(e);//instantiate here and then wait
        yield return null;//this line prevents lag
    }
}
//...
StartCoroutine(CreateObjects(data));
//...
  1. Having many active game objects is also costly especially in mobile devices. If many active game object have heavy scripts, the update methods will ruin performance. If many active game objects have rigidbodies or colliders the physics engine processing gets heavy.

  2. Activating game objects is costly but less than instantiation, since it only runs Start method on its script if any, and also causes the physics engine to re-evaluate its structure if it has static collider or rigidbody.

  3. Rendering is costly if only the rendered visuals are (fully or partially) visible to the cameras.

  4. Create an editor project where you can design your levels. in this project you will make use of unity's editor classes to generate some kind of data (JsonObject) which represents your whole world. (collection of levels, tiles in each level and objects in each tile). Moreover you can have other data such as objectives and stuff each stored in a different JsonObject. Then use this data in your game by reading it and storing its structure in memory.

    • The reason I recommend JsonObject to store data is its size, portability, flexibility, accessibility and simplicity to work with. JsonObject is a dictionary stored as a plain text. and since it's a text you can encrypt it as you like