The Apartment

Blinds

Animated GIF of the shutters being manipulated by hand.

These objects would be placed in the level, and feature both as a method of closing the outside world whilst loading, and look outside without people noticing. It was originally designed to support two hands, but could have more hands in case the user wants to stick the entire camera in the blinds.

Vertex colors applied to the blinds.

Making these blinds was very nice. It makes use of vertex colors to define what areas can be moved. Each panel has their own material with parameters. Different channels would move differently. The green channel would move the vertices horizontally, allowing the edges to move inward during interation to maintain their length. Red vertices freely move towards the position defined in the parameter, which is a fixed height above, or below the hand, depending on if the hand started above or below the panel.

Whilst working on an older project I have learned that too many dynamic material instances slow down the game. That is why I maintain a cache of instances. The system allocates these instances to blinds that are currently interacted with, and prefers the instances closer to the hand. If a blind is 'released' the instance is maintained, but a lower priority, allowing it to be reused for a different panel. Also when a panel has been declared unused, it shares the same non-dynamic material as most of the panels.

Save System

Unreal Engine 4 makes it easy to build on top of their serialization methods. At the time of development the game was not fully designed yet, so I came up with a very flexible save system that can be utilized using Blueprints.

It works by having your objects inherit from an interface. And on saving and loading, it would collect all objects that use this interface, and run a set of steps.

Additionally, objects can register themselves as global objects. They are persistent across all saves, and do not need to be destroyed and reconstructed. Also objects can use the interface for other purposes as well, such as removing itself from the level upon loading.

A common problem with saving is object relations. Pointers break, so we need to fix those issues since we have objects spanning multiple levels. To do this we have a registry. Objects can register themselves, or others, using identifiers. When serializing we store the identifier on saving, and lookup the identifier to find the matching object during loading.

Finally, there is a master save that is used for keeping track of all save games. This file can also contain additional information per save slot, such as time played, the level, or more.

These steps would run upon saving:

These steps would run upon loading:

The end result is a very flexible system that makes it easier to serialize references, makes use of UE4 as intended, and can be considered as robust (if used right).

Project Abby

Branching Narrative

In Project Abby you are supposed to walk around in a room, and you can analyze a couple of objects. If you think you have explored enough you can leave the room, and answer questions. Depending on your earlier answers, and which objects you have analyzed, different questions and answers might pop up. Each time you return to the room, it could be different, since each room visit is on a different day.

I may have over-engineered this. My solution is to let a designer user Twine to create a story. Twine can be used to write, and link passages. These passages could branch off to different passages. Advanced usage of Twine allows the usage of variables. Twine works by exporting the story to HTML with Javascript, which then runs the story.
Since I did not want to run Javascript, or recreate the entirety of Twine in UE4, I decided to use Twine more of a tool for the designer to use, and tell the designer how to exactly format the nodes, and how to write the syntax for accomplishing the same thing as Twine.
Next I wrote a tool that converts a Twine story to bytecode, which I then ran on specific events in game, and would continue to run until the bytecode returned with a question and a list of answers, or a different command.

This topic intrigues me very much, and I definitely want to do more research in lexers and syntax.

Ambient Audio

This project gave me the chance to implement audio for the first time, and I chose to do ambient audio. My goal was to keep the ambience present, but always in the background. It should not sound like it is looping, but it should never sound out of place.

My solution is a system that would have a list of assets, and their properties, and schedule them. It would make sure that sounds do not play too often, and because the volume is known for each sample, it would make sure that loud sounds will not overlap.
To prevent samples from growing familiar, sounds would vary in pitch and volume.

The properties a sound asset could have are:

The sound shape is more useful for longer samples. The reason for these shapes is to allow sounds to overlap, knowing it will not be too loud.
Note that the min/max time between samples is just a suggestion, if a sample does not fit, it does not play. If desired the min/max time could be set to 0, and the priority to 0 as well, causing the sample to always be audible, but other samples can always go first.

I wrote a program that could load .wav files, displayed their loudness, and suggest a value for the sound loudness, and a shape. Trying to do this leads to a whole lot of papers and arguments on how to measure loudness, and human perception of loudness.
To cut that short I ended up implementing Root Mean Square, since that one looked do-able to implement. The curves I found looked accurate.

If I had more time, this is definitely something I would expand on. The system could output to multiple audio sources, but they would play the same. In our New York settings a helicopter flyby, and the barking dog sound approprioate, but either the heli is in your neighbours apartment, or the dog is abseiling. Separating the sources meant that the systems may overlap.
Variety is still a concern. Improvements could be made in grouping sounds together, so that the dog sometimes barks once, and sometimes three times, without featuring multiple sound assets.

GridBrawler

Decal Baking

In-game screenshot of nuts and bolts on the floor

In the picture on the right you can see a wireframe, and the scene. What has happened is that I just tossed a bunch of nuts and bolts around, and the old bolts are not visible in the wireframe. Because I baked them in the floor texture. Kind of exiting to allow for so much detail to appear without any issue. This was part of my first project in Unreal Engine 4.

In the game I toss quads with textures around, and when they land on the floor they bounce until coming to a complete halt. I then update the texture data in RAM. After a bunch of quads are processed, I commit the textures to video RAM, and delete the quads.

Updating textures can be quite expensive, so I subdivide the texture into multiple textures of 256x256. Performance was negligible.

Shadertoy

Raymarching

Shadertoy and Raymarching ways for me to create cool stuff. It allows for geometry we are not used to seeing in video games. Demonstrating raymarching to artists I am familiar with breaks their minds in no-time.
I used this tool to experiment with shapes, rendering, soft shadowing, and color spaces. More on the last one later. I think this can be best summized in a bunch of images. Shadertory Profile

Shadertoy 1 Shadertoy 2 Shadertoy 3
Shadertoy 4
Shadertoy 5 Shadertoy 6 Shadertoy 7

Log color space

I always enjoyed working together with artists. I do not often get the opportunity during a project to work with artists, but I try and have the technical knowhow on how different features work in engines. UE4.15 came with a new tonemapper, and that triggered me to perform research on log color space, and the merit it has for video editing.