5
\$\begingroup\$

I've always wanted to create the type of map generator they use in Kingdoms and castles. Basically you provide a seed, and it generates land/water/trees/resources. Their maps are also completely flat (except water seems to be 1-2 positions down, which I assume would make it easier.

enter image description here

However I do not know where to look for guidance for this type of system, I am wondering if anyone can explain the logic of how that type of system works, or even better, point me to a tutorial that could get me started.

While there are tutorials on perlin noise and the like, I never really understood how to connect it to a proper tile, and what properties that tile should have, does it need colliders? is each tile a gameobject? If not, how do I create tiles with trees/rocks that I can gather? and so on.

\$\endgroup\$
  • \$\begingroup\$ I edited your question title because the question gave the impression that you are looking for procedural generation algorithms and then only in the last paragraph you make clear that you actually don't look for an algorithm but for a system to represent the output of that algorithm in your scene hierarchy. \$\endgroup\$ – Philipp Nov 23 at 13:34
  • \$\begingroup\$ Thank you, that was indeed confusing \$\endgroup\$ – Green_qaue Nov 23 at 13:49
  • \$\begingroup\$ You may find Building Minecraft Villages with AI - The Minecraft GDMC | AI and Games interesting. \$\endgroup\$ – Theraot Nov 23 at 14:06
3
\$\begingroup\$

I myself am a procedural loving person and I have done a lot of PCG. From experience, I can say that procedural generation is too broad to define on "how to do it". There are lots of ways on how you can approach reaching some goal. That is a part of fun in procedural generation that every algorithm has something of its own and unique in some degree.

Of course we can generalise some things and look at some common approaches. But first let's ask a question: "what is procedural?".

A lot of stuff I write here is opinion based. I am trying to share what I understood from a few projects with procedural generation. So I don't think it's ideal or something that defines PCG.

What I mean by this is that procedural isn't random. It utilises randomness in order for it to be procedural? More or less - yes. But I like to think about the result being procedural, what you get in the end is procedural. Placing a few objects at random places, I wouldn't call it procedural, but generating a map of objects placed randomly, following some rules to make sense - that is what I think is procedural.

I will try to define general approaches and try to guess the specific approach that was taken to generated this map from an example that you have shared.


Noise generation based.

Developers frequently take this approach because there is wide variety of different forms and shapes of textures that are being generated and they serve for different purposes allowing for generation of all kinds of shapes. Very common is to use textures for generating height maps for terrain 0 being at lowest point and 1 being at the highest point on the terrain.

Textures are just random numbers from 0f-1f at each pixel. How those random numbers are generated for textures depends on the rules set for generating such a texture. So basically you can do the same thing just with random number generation without using a texture, but sometimes you want to save that data, to speed up some processes, to have a visual representation and so on... This is when textures are handy.


Just random.

The most common one and a base for everything else. Just using random numbers for indices and values to randomly place some object, extend it in some direction, create random positions for mesh vertices...

Nothing is truly random in most Random modules. They are just mathematical functions that will give the same result provided the seed for them was the same.


Fractal based.

Beautiful forms that generate itself from the same rules.

Wiki:

There are two major methods of two dimensional fractal generation. One is to apply an iterative process to simple equations by generative recursion. The other main method is with Iterated Function Systems consisting of a number of affine transformations.


Other.

Maze, Dugeon, Random Tree, L-System...

PCG Algorithms

There are lots of algorithms not to only generate maps, objects, and 3D. But text, dialogues, behaviours, story chain...


Example from question.

The approach I would take to generate this kind of a map.

Setting up Random module to take an int/long seed. Based on this seed we will get random values from our module that would change the world to some extent every time we change the seed and regenerate everything.

First thing that we would need is a tile map. Just a map that represents a grid of tiles Tiles[10,10]. It could be a 3D one and more Tiles[10, 1, 10], we could even store some other information in that array, it doesn't really matter. But for this one I would choose a 2D tile map as this is enough. Tiles are not necessary GameObjects or even classes [I usually make them classes or structs]. They are just convenient containers holding data about tile, like its position, indices position in array that holds them and other valuable data for your type of generation.

Generate river, lakes, grass, sand tiles. For each of the tile type you could define it's own rules of generation. Generate river by using some algorithm that would simulate behaviour of river.

Then I would scatter resources like trees, rocks and everything natural. I would generated them on some tiles defined by some rules. Like pick a random location, place tree, trees grow close one to another, close to water, place some more trees until its enough and still under limited number of trees.

Then I would generate roads by using path-finding algorithm like A* for simplicity. Or I could first generated buildings - then generate roads. Or first generate the castle, then everything else. It all depends on the result we would like to see in the end.

It's really that simple and there are no things like generate neat texture then generate everything else based on this texture - it's still possible though, if you need this.


Colliders. They are widely used during process of generation. Usually to simplify rules or provide tools for human interaction with generation.

For example,

  1. you could use colliders to check if something overlaps or can fit in during placement [when you don't have strictly defined bounds or you can't utilise those bounds to achieve your generative goal].

  2. you could use colliders to allow designer to meddle in how something is generated. [Blocking tiles, marking them walkable, allowing generation on them, setting some rules for the area...].


It's easy to create something procedural. But it's hard to make it fun and less repetitive, once you master generation, you have to master another field. And that is generating something unique and quite different from previous experience. You can see many patterns of repetitiveness in lots of games.

In the end. Everything that PCG is can be boiled down to randomness, just random numbers. It's the way we use those numbers is what defines the shapes and forms of content we can create with them. And from those we create algorithms, techniques and new ways of morphing those random numbers into sets of other types of randomness.

\$\endgroup\$
  • \$\begingroup\$ Thanks! I was thinking, if I create a 2d array of values using perlin noise, they will all get a float value. Instantiating cubes at the coordinates in this array is simple enough, but lets say I have the tiles you mentioned, each being a represented by a 1x1 cube, how would I decide which value in my array represents a water-tile, grass-tile, etc. ? Actually the more I think about it the more I think I need to make this a seperate question. \$\endgroup\$ – Green_qaue Nov 23 at 15:49
  • \$\begingroup\$ @Green_qaue if you want to approach it with texture generation [2D array of values from 0 to 1 is basically a texture in a nutshell] then you can have different ranges of value decide what type of tile it is. For example, value from 0f to 0.12f could be a water tile, value from 0.12f to 0.14f sand, from 0.14f to 0.8f grass, everything higher than 0.8f could be rock. \$\endgroup\$ – Candid Moon _Max_ Nov 23 at 16:07
2
\$\begingroup\$

As with everything in Unity, there is no one way to do things.

Using a full-fledged game object to represent each empty tile can be a viable approach if you have rather small maps. But if you aim for a very large game world (perhaps even infinite), then the memory, CPU and GPU overhead of many small individual game objects gets too large and you will run into framerate issues.

You can drastically increase the limit of how many simple game objects you can get away with by using the new DOTS architecture and representing tiles as lightweight Entities instead of full-fledged game objects. That means if you are brave enough to face DOTS it in its current (late 2019) half-finished, spotty documented and poorly understood state.

If your terrain is entirely 2d and consists of square tiles with hard edges, then you could implement it as a Tilemap. Just because it is intended to be a 2D component does not mean that you can not use it as a spacial plane in a 3d scene.

If your terrain is 3d, then you could use the Unity 3d Terrain system for it. While the usual way to use 3d terrain is via the editing tools in the Unity editor, you can also create a terrain entirely procedural via scripts by changing its terrainData property.

If the aesthetics of the Unity terrain component aren't suitable for your game and you would like to have more control over the exact terrain geometry, then you could create your map as one single GameObject with a procedurally generated mesh.

And then there are of course assets on the asset store you can buy to save development time. Disclaimer: I didn't use any of these assets, so I can not vouche for their quality. But two assets which look quite promising to me are Terrain tile editor and Tycoon Tile.

does it need colliders?

That depends. Do you want to use rigidbody physics? Most citybuilder games do not have much use for the physics engine, so the terrain doesn't really need a collider. But if you do use physics, then you need to give your map a collider in order to prevent objects affected by gravity to fall through it. Do you want to use the Unity pathfinding system? Then you also need colliders.

  • If your terrain is flat, then a single BoxCollider will do the job.
  • The TileMap Component can create its own collider based on the tiles it consists of, but that collider is intended for 2D game objects which move across the tilemap, not for 3d objects colliding with the tilemap as a whole. However, if you have entities which are objects in your game which are supposed to navigate the 2d terrain and can not move across every kind of tile, then the TileMap collision system could be of use to you.
  • The Unity Terrain system already comes with a collider.
  • If your terrain is a procedural mesh, then you will have to use a MeshCollider for it. If your terrain is large and complex, then you might have to break up your MeshCollider into multiple ones for performance reasons (mesh colliders with high polygon counts can become performance hogs).
\$\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.