Wednesday, August 21, 2013

Procedural Geometry Dungeon Generator

Over the last week we've been working on a procedural dungeon generator.  Not really for any particular game, just as a "hey, this is kinda neat" project.

I wish I'd been posting about it as it's progressed, but then I'd have less time for coding :)

This is just a quick catch-up post about the progress so far.

. . .

But first, what exactly is "Procedural Geometry"?

Well, instead of using models or prefabs in Unity we build the meshes ourselves, specifying the vertices, indices, texture coordinates, etc.

Why would we do it that way?

Well, for one thing it's blazingly fast.  We can generate a 256x256 "tile" dungeon at run-time, geometry and all, in well under a second.   And believe me, that's a big dungeon when you start moving around in it.

Doing a dungeon that large with prefabs, at run-time is problematic for a number of reasons if you don't approach it in the right way (but it can definitely be done).   The first approach most people think of is to just use GameObject.Instantiate to add prefabs.   But a 256x256 dungeon ends up adding over 65,000 objects to the scene.  It works, and Unity can handle it, it's just slooow.   (Note: instantiation isn't really what slows it down, it's the voodoo that Unity does between the Start and first Update, at least according to the timings we've done while playing with the process.)

So let's do this procedurally for now... and see what happens.

We want to support dungeons up to 1024x1024 (or bigger?!) so we did end up "chunking" the dungeon by breaking it up into multiple meshes.   We had to do that due to Unity's limit on vertices in a single mesh.

But the chunking also helps out with performance by letting Unity frustum cull and only render the chunks that are visible.

But none of that is the fun part... let's talk about how we've progressed the generator.

. . .

Click the images below for bigger views.

First steps:  build the basic geometry of the dungeon...



Not exactly exciting, so let's spice it up a bit by adding pits and bridges.



Better... but still nothing to write home about.  It's a little flat looking.  Obviously textures would help, but we'll put that off for now.

Speaking of textures, you may notice the columns for the bridges are just hanging there.   We'll take care of that later with texturing (or possibly a custom shader).

So what can we do to make the geometry more interesting?   Hmmm.. how about borders around all the edges.



It's getting there, but even the borders are boring... so we'll spruce them up.



There.  The basic geometry is okay (at least for what we're trying to do).

So what now?

Let's texture it!  I think we're going for a "retro pixel" look, but still keep it "kinda-sorta realistic" (meaning no 8-bit bright colors).

And let's be honest here, "retro pixel" is attractive to me because I can't make decent high-res textures to save my life!



The single texture used above is 128x128.  Nice and tiny.  We could scale that up to add more details, but that works well for the "retro pixel" look we're shooting for.



Notice the black fade... that's saves our "dangling bridges and pits" from looking weird.   The texture is a little wasteful, so we may come back to that later.   We could add semi-transparent water or lava or green slime as well and it would still look nice.

But let's get back to the dungeon...  It's still not looking quite the way we want it.

How about some lighting?   We're using a projector (Unity built-in) to color and light the dungeon.   Why?  Well, it'll let us provide "Fog of War" type lighting easily if we want to later in the project.



But wait... what dungeon is complete without columns...



... and doors.


Yeah, it makes absolutely no sense to put the doors in as static geometry.  They should be placeable prefabs.  *shrug*

And let's test by generating a 256 x 256 dungeon:


. . .

And that's it for now.

Next time, I'll discuss adding colliders and walk-meshes and how we actually generate the dungeon data.

The current version works both generating the dungeon inside the editor (useful for adding walk-meshes) or at run-time (useful for random "rogue-like" games).

We'll also support saving to and loading from files.

No comments:

Post a Comment