How would i procedurally generate caves

I know this topic has been covered before, however my case is slightly different.
I’ve generated a ‘hexagonal’ world like so:


Each hexagon is one mesh that’s 150 long on the y axis, I want to generate caves without the need of stacking tons of hexagons on the y axis then using perlin worms etc to remove the hexagons, this would be very expensive for performance.

Instead, what i was thinking of doing is something like this:


This is a cross-section of the ‘hexagon terrain chunk’, noise will dictate where the empty space is and another noise will dictate the size of the empty space, This way, there is at most, 2 hexagons in one cell of a chunk.

There’s a few issues however, I’m not sure how I can replicate this on a 3d scale (having the cave move up, down, left, right and also making the cave wide / thin) and how I could make sure that each cave has a starting point on the surface.

I did a fairly bad job explaining so please let me know if you need me to elaborate, Any tips are appreciated too.

3 Likes

This is such a cool idea! I’ll give it a try and report back…

You could still use perlin worms, what I’d do is this:

  1. Create two layers of hexagons.
  2. Calculate the cave’s heightmap using perlin worms
  3. Apply half the height to the top layer
  4. Apply the other half of the height to the bottom layer

This would create this:
image

Then apply some noise to randomise the height a bit to make it look less uniform, or you could apply another layer of noise on the bottom layer.

Sorry if this doesn’t make sense in text, it makes more sense in my head.

2 Likes

Map Gen.rbxl (25.8 KB)

Here’s my approach, giving results like the above image.

It walks over each (X, Z) tile coordinate of the map (so 8 studs resolution in this case), and then walks through every Y coordinate, so 1 vertical stud per step, starting at the top of the level. It keeps track of whether or not it’s already “got” a part. If it has a part and the next step is solid, make the part 1 taller and move it 0.5 down. If it has a part and the next step is not solid, don’t make the part taller and “finish it”. If it doesn’t have a part and the next step is solid, start a new part at the current Y coord. If it doesn’t have a part and the next step is not solid, do nothing. Or in code

function generateTileAt(x, z)
	local currentTile = nil
	
	for y = -MAP_HEIGHT/2, MAP_HEIGHT/2 do
		if isSolid(x, y / TILE_SIZE, z) then
			if currentTile then
				currentTile.Size += Vector3.new(0, 1, 0)
				currentTile.CFrame -= Vector3.new(0, 1/2, 0)
			else
				currentTile = TILE_PREFAB:Clone()
				currentTile.CFrame = CFrame.new(x * TILE_SIZE, y, z * TILE_SIZE)
				currentTile.Color = Color3.fromHSV(0.2755 + math.random() / 5, 0.314107 + math.random() / 10, 0.611765 + math.random() / 10)
				currentTile.Parent = game.Workspace.Tiles
			end
		else
			if currentTile then	
				currentTile.Parent = game.Workspace.Tiles
				currentTile = nil
			else
				
			end
		end
	end
	
	if currentTile then	
		currentTile.Parent = game.Workspace.Tiles
		currentTile = nil
	end
end
1 Like

That could work, I’ll have to give that a shot, do you have any re-cap videos on perlin worms i need to refresh my mind.

Firstly, I really appreciate the effort you put in to help me out, I’ve tried implementing this method into my game aswell but it didn’t turn out as expected. It would give me cracks in the ground instead of caves. I’ve heard of this method before too, it works better with voxel-like terrain where there’s cubes stacked ontop of eachother I think.

The main problem i faced though was widening the cave, it would make only crack-like caves in the ground.

If anyone wants, here is the place file: MapGeneration.rbxl (95.4 KB)
The script is under startercharacter scripts, see what you can do from there. I’ll be giving the perlin worms a shot tomorrow once I’ve gotten a re-cap on them.

Not sure if these are helpful, but the developer forums seems to have a lot of threads about it already. Unity and Unreal has a lot of discussion about it too, and of course our biggest friend, Google.

1 Like