Voyage To Valhalla

Voyage to Valhalla was a VR prototype that I worked on with a group of 3 artists and 2 other programmers. The premise is simple – you float down an endless river, hoards of vikings throwing all manner of hurt against you, and the only tools you have at your disposal are a shield, a blender, and whatever weapons they’ve hurtled your way.

Procedural River

One of my main contributions to the project was programming the game’s procedurally generated levels. The backbone of this system is a spline that gets continuously extended at runtime. Each point is given a slightly random offset position from the preceding point to give the generate level the impression of a naturally winding river. The river itself and adjacent banks are constructed from a series of meshes that are curved to match the direction of the spline.

These images show some of the early prototyping stages of the river’s construction. Initially, I just got the system to a point where it would evenly place planes along the length of the spline. Once our artists had pushed some preliminary meshes to the project, I created a Segment actor that could contain all elements of a section of the river including the river’s water, banks, trees and bordering mountains.

By using Unreal’s built in support for spline meshes, I was able to blend the segments together seamlessly. Only the meshes that form the terrain of the map needed to be converted to spline meshes since it would warp other objects like the houses and trees in strange ways. With the base geometry of the river established, I set up some preliminary randomization that would provide a foundation for further variety once more art assets were added to the project.

As the river continues to generate, old segments are destroyed to prevent them from unnecessarily bloating memory.

The segments themselves are constructed from nested child actors that are selected from at random. For instance, some sections will spawn forests, others with spawn houses.

Within each of those child actors there is randomization for the transforms of those trees and houses, and they can probabilistically spawn additional meshes such as rocks, fences, docks, vegetation, and campfires.

Fairly late into development we also added seasonal variations to the level. These were aesthetic changes that gave the generated river an even greater sense of variety by cycling the seasons after a certain number of segments. For most objects in the scene this just requires swapping out the object’s materials for a season-appropriate variant. Some meshes such as those for vegetation like flowers were only placed during the warmer months. Forests spawned leaf piles during autumn and most segments had patches of snow during the autumn and winter. The winter biome even has bobbing ice at the edges of the river.

Enemies

Outside of level generation I was also responsible for setting up variants for all of our enemy blueprints. To do this, I created a component that held a map of equipment slots to a list of equipment associated with that slot. When the enemy was created, the component would randomly select a piece of equipment from each slot and assign it to the corresponding skeletal mesh on the character.

To ensure that each piece of equipment would actually move with the body of the enemy, I had to set the leader poses of each equipment mesh to that of the main body. There were three different enemy types in the game: axe-throwing vikings, spear-wielding Valkyries and boulder-tossing giants, and each of them required a similar set up for their equipment.

Obstacles

Besides enemies, we created a number of obstacles that would be placed in the path of the player’s boat by the level generation. If left alone, the boat can crash into these obstacles and hurt the player. So in addition to fighting aggressive enemies player’s need to be aware of their environment and take out the obstacles by throwing their weapons at an obstacle’s weak points.

A weapon can be thrown at an iceberg or root to make it shatter, or at the load point in the drawbridge to raise it. Some obstacles can have enemies positioned on them and breaking the obstacles also eliminates the enemies. In the case of the root, it serve purely as another vantage point for enemies and not as a direct danger to the player.

Blender Crafting Mechanic

This was one of the more fun parts of the project that I got to put together. During development, we had many discussions about finding the right balance of activities for the player to do on the boat. Since they can’t leave the boat, there’s the risk of a player clearing out all the nearby enemies, leaving them with nothing to do until the boat reaches the next encounter. On the other hand, we didn’t want to give the player so much to do that it was overwhelming. The solution that we arrived at was a simplified crafting mechanic in which players could grab the fish that sometimes flew past the boat and use them to craft enchantments.

Whenever a player grabs a yellow or blue fish, they can throw it into the blender and convert it into enchanting oil. I animated the process using a timeline that rotated the blades and sucked in the fish as it gave the fish a bit of random jitter. Since we had already implemented being able to eat the fish to restore health, I had the blender spit out the consumed fish skeleton once it was done. Events on the timeline are used to plays sounds and VFX.


Voyage to Valhalla was a successful prototype that I think could be worth revisiting. At the time of making it none of us had much experience with VR and we were working with fairly unreliable devices. I’ve since worked professionally as a dev at a VR studio and know that with a bit of work it could be polished into a really fun and complete experience.