Floating Island – Part 1

I’ve decided to deviate from the path I was following, learning proceedural generation by ProjectSalt’s example. With that I’ve begun turning this into an actual game because I thought it was fun to work with and I have a decent idea for where to go with it.

Without further ado, the next step is making floating islands! It’s a big step up from having basic heightmap terrain islands on ground level because a floating island demands more interesting geometry, not to mention we now need some form of bottom that can be viewed from down below. Now you might imagine that we could still use the single plane approach from the ground islands and simply have clouds around it to disguise the hollow bottom, but my vision extends beyond that, which is also why I cut this step into several parts.

My first step was to do what I do on ground level and just elevate the new islands.

Bunch of underlying code reworks to make new type of island and dedicate a whole new grid to the floating islands so that they can appear on their own without ground island interference.

Next step is to create a suitable bottom for our island, which can be done with close to the same steps as when creating a normal island, but instead of using randomness to create height we’ll be taking control instead. Make another island the same size as the floating one and extrude the vertices downwards the closer they are to the center of the island. Make sure to flip the triangle directions because we’re technically looking at the inside of the mesh and not the surface. If we also add the round island mask for our normal islands we’ll get a rounded bottom that snugly fits the circular shape of our island.

So now we have an ugly square floating island. Before we could get away with not cutting the edges of the ground islands because our water covers that anyway so it wasn’t really an issue, but now that we have a floating island the sharp rectangle edges are a huge eyesore, so let’s start the cutting process and make this a nice smooth round-edged island instead.

The approach I’ll use is identifying parts to cut away with the island mask. Black in the mask represents parts that should be cut away. Since I’m using a round mask the cutaway becomes a lovely circle shape.

In order to make more interesting cutaway shapes we could modify the round island mask with noise. Make sure the bottom also uses the same noise values so there’s not a disconnect between the island and bottom. I never did arrive at an interesting difference in the cutaway shape, not interesting enough at least, so I decided to grow a bit more bold and cut away all triangles that went below height=0 in model space. Vice versa for the bottom. This left me with some gaps into the island but much more interesting cutting patterns for the islands. Patching up the triangle gaps by making new triangles that was based by the cutaway triangles but instead capped at height=0.

I left the edge triangles in constrast with the island itself to see where they were cut and patched. It’s a little bit patchy and what not, but significatly more interesting then the timid circle shape we had before.

This will have to do for now for this part, but rest assured we’ll be revisiting the issue of the floating islands in the future.

Islands of plenty

Now we can walk on islands, move between them and even explore what islands are out there. There isn’t lengthy fun to that however, seeing as our islands are bare and devoid of life. Let’s see if we can’t add some lovely trees and bushes to fix that problem. Let’s also try adding some wildlife to our islands.

I visited the Unity Asset Store and quickly found some nice looking environment. The environment asset package I’ll be using is made by A.C. It’s small but it’s free and it serves the purpose of populating the islands a little to make them more interesting. This pack comes essentially with 2 variations, Green vegetation or red/brown vegetation. I’ll be treating these as different biomes. I approached flora instantiation simply by randomly firing a bunch of rays downwards onto the ground within the scope of each island and then processing this information, figuring out if  the spot is safe to place vegetation or not e.g I don’t want to put tress or grass on sand or cliffs. But we already did checks like these when applying colors to the terrain so it’s easy peasy to just redo them here.

Already our islands feel much more vibrant and alive. Tweak your vegetation density all you want to create more or less barren environments to full and lush ones.

Now we have flora, now we need fauna. I went on the asset store again to aquire some free assets and I found a horse made by Dootsy Development with 3 animations. Idle, walk and run. Works perfect as an example when animation controller is tweaked and we add a NavMeshAgent to it. Now we need a navmesh that the fauna AI can walk upon. For each island I make a NavMeshData. I used the island mesh as a NavMeshBuildSource and got the default NavMeshBuildSettings through NavMesh.GetSettingsByIndex(0) for the NavMeshBuilder.BuildNavMeshData call and then added the created data to NavMesh.AddNavMeshData. Now I can raycast points across the island terrain and set those as the horses target destination and they will navigate to it if they can.

Multiple islands and a boat

So, now we have our island proper with water. What is the next big thing about ProjectSalt? Multiple islands and sailing between them. That means we need to be able to generate different islands that are both random and the same for the same world seed. We need a couple more things like being able to walk on islands and have a boat that we can use to get to the other islands.

To deal with the walking on the islands, I use a mesh collidder on my island, feed it the mesh, and then instantiate a Unity Standard Assets FPSCharacterController. It casically works right out the box and we don’t really have to fuzz about anything. It could use some serious tweaks and a little bit of script changing, but it get’s the job done.

Now that we can traverse our island, we need another island to go to. The easiest way to do that would be simply to create a second island or copy the one we already have and place it a bit away, but where’s the actual fun in that. We’ll start by imagening that the world is split up into rectangles. The useful thing about that is that we can put an island into each rectangle, the max size of the island being the rectangle itself if we choose too, and we’d never have any intersecting islands unless we specifically wanted them to, say for example to make larger islands. Now we need to find proper random numbers so we can put islands around us on the grid, and a sequentially seeded Random function won’t do the trick. I found a blog post by Rune Skovbo Johansen dealing with exactly what we need. I ended up using the XXHash class he mentions and so far it works like a charm. We can now generate random numbers that will both be reliably the same when revisiting the island and still have a great randomness.

Now that we have multiple islands, we’re going to need to be able to move between them. We need a boat. The simplest way to make a boat would be to simply have it travel along the ground plane in a direction of our choosing, but again, where’s the fun in that. We’re going to implement it proper, waves and bouyancy and all.

First, we need to be able to sample the waves so that it feels like we’re actually moving across a body of water that’s in motion. We can do that quite simply by mimicing the scroll function in the water shader, but on the CPU, and sample the texture with that offset. The sample functions behave roughly the same so it’s basically just copying the wave offsetting part of the vertex function in the shader and put that in a script.

Now that we have the ability to sample the height of a wave at any given time, let’s make it a bit more exciting by actually using bouyancy. We’ll be using Archimede’s Principle for this endeavor. I found a great video by Khan Academy that really rocks going through the mathematics behind it. I also came across a great post by alexzzzz at the unity forums with a very useful bouyancy script that we can almost use right off the bat. I only used a small part of it but as I understand it you’d be able to use arbitrary objects for bouyancy as it creates a voxel representation of the collider to simplify the math. You can use the script just as it is or only the most useful parts for our goal, makes no difference, as long as it floats on the waves and we can use it to get to our next island.

Now that we have our vessel of transportation, we can move in between islands and explore the world!

 

P.S
Don’t forget to add bouyancy to the player character!

Island

First things first, and credit where credit is due; I’ve stumbled across ProjectSalt on Steam and been playing it for a couple of days. Being a fan of exploration games and carribean style-ish pirate games it seemed like a game worth trying. After a few days my inspiration levels had risen quite high and I decided that I wanted to make something similar and try my hands at proceedural generation as I had surprisingly little experience with it after all these years.

So, what’s the core of ProjectSalt? Islands. How do we make an island? ‘Tesselating a vertex field!’ … was my original thought, but in the end I reeled myself in and took the easier approach and created a terrain heightmap. My approach was to make use of a couple of Unity’s Mathf.Perlin calls, which is practically infinite in randomness, and mix them together. After tweaking a couple of numbers and settling for an island to follow throughout the tutorial, I ended up with this heightmap:

Now that I had that, I could proceed to creating my terrain. Treating each pixel as one vertex I could now just make a vertex field with the same number of vertices arranged in width(x) and depth(z) as the texture had corresponding pixels of width(x/u) and height(y/v). With the heightmap at the ready I just sampled the height from the map at each vertex and ended up this:

 

Nice looking terrain, huh? I thought so too until I quickly figured that ‘This doesn’t look very much like an island, let’s fix that!’ and so I had to smooth the edges somehow. I did this by using a circular, smooth-edged texture mask when creating the heightmap, so I could sample it at roughly the same uv as setting pixels in the heightmap and mix it with the final perlin noise. It turned out pretty well!

It’s shaping up, now it actually looks like it could pass for an island, doesn’t it? But it’s still missing some stuff, like a shader to add some sand, beach and cliffs. For shading a terrain, you usually make do with splat shading, which is most commonly that the vertices in the terrain will also have colors, as opposed to the normal positions, normals and uvs. These colors map in the shader to a specific texture and such you can paint a terrain with colors and get your textures “splatted” onto the terrain. The way I set mine up was that red color was for beach, green color was for grass and blue color was for cliffs. So I had to decide some things, how high should the beaches be and at which steepness did cliffs appear at. After doing that and making the shader, I ended up with a much nicer looking island than just a dull grey one.

 

This, this is an island. After admiring my new proceedurally created island, I felt like I was missing something. What kind of island doesn’t have any water surrounding it!? No island at all I say. So I ventured to make some water and at first I thought ‘Let’s make a huge vertex field in code and make it all wavey!’ … Then it obviously hit me that it would cost a buttload of processing power, time and energy to make something like that efficient and fast enough so I decided to go the easier route and let my GPU do the work for me at minimal cost instead.

I put a bunch of planes with a decent vertex density around the world and made them a shader with a basic water texture and a one color waves texture. Now I could sample the waves texture in the vertex shader and extrude the vertices up(y) to make some static waves. (FYI: This approach might not work or be the optimal approach for some older phones.) I made sure to use the vertices world xz coordinates instead of the normal uv texture coordinates to sample the waves texture so that wherever I moved the water in the world, the waves would show as they would be at that position in the world. That makes it easy to move the planes of water along with the player and he/she would be none the wiser that we’re doing it. All I had to do now was to scroll the waves texture along some axis at some speed and I would have some dynamic waves. It looks pretty good with minimal effort, time and processing power all in all.

So in the end we ended up with our island, surrounded by moving waves. How nice!