Before you read on, I'd like to forewarn that this project involves flashing, bright lights, repeating patterns, and loud noises, which could be an issue for people who have photo and/or audio sensitivity. Please exert discretion when going forward!
DISCOmfort is less a game and more an audio visual experience. I created it in my final year of study in RMIT. The point of the exercise was to practice my environment art skills. I decided to create a caricature/parody of a night club, because I notoriously dislike them, they evoke deep DISCOmfort from me (pun very much intended), which is why they serve as an excellent setting for creating something exaggerated, so I took every aspect of the things that make me feel uneasy in a club and depicted them tenfold.
The character movement was the only asset I downloaded from the Unity store, everything else is made by me.
Engine: Unity URP 2019 LTS.
Release: A full release was made on Itch.io, and you can play it here for free.
Production Period: Made in a little over a month in 2022 while studying at RMIT.
Music: All credit for the music goes to my friend Josh Hickman.
Notable Features:
VFX, Shaders and Post Process: All the shaders and particle effects were done by me using Unity's Shader and VFX graphs, further leveraged by using URP's post process effects. Some examples include the characters smoking, screen deformation, ambient fog, full screen color distortion, etc.
Animating: All the dancing characters were modeled, rigged and animated by me using Blender, afterwards being imported into Unity using the skinned skeletal rig system.
Programming: Using C# through Visual Studio, I created some scripts that automated some manual tasks and generally empowered the character animation pipeline. Example: randomly picking a facial expression, offsetting dance animations by a random amount of time, always face the player when they approach, etc.
Below I'll go into detail about the areas of this project which I find most noteworthy, and breakdown how some of them work (lots of text incoming!):
Starting with the most apparent, the post processing does most of the heavy lifting here to create the psychedelic aesthetic of a heavily intoxicated visit to a night club. To communicate just how important post processing has been here, here is a picture of the same environment with and without the post process:
Quite the contrast! There are lots of overrides in the post process volume that I use in the scene, as you will see in the image below:
I added effects that would deliberately cause the image to distort, such as chromatic aberration and motion blur, to really sell the idea of intoxication.
But the most important one I need to highlight in Tonemapping. Normally, this override would be used to colour correct the game between bright and dark areas, and create stronger contrasts. But I found that by reducing Gamma to a miniscule value, it creates the effect of hyper contrast between light and dark.
In any other context this would probably just break the visual cohesion of the experience, but in my particular case, this game works really well with this look, it really sells the idea of being in a bad trip.
This result was not initially intended. I was messing with Gamma's "real" purpose in an attempt to make better contrasts, but ended up with this happy accident instead.
The first shader I want to talk about is the screen distortion as seen below in the blobs floating around:
To anyone who works with shaders, you will immediately recognize this as voronoi, and its use here is quite simple. It's just voronoi being applied over the top of the screen's position, which causes everything being rendered in the scene colour to distort.
However I want to show a small bit of ignorance I had at the time, which I solved with a bit of ingenuity. At the time, I did not know of the existence of the "Fullscreen Pass Renderer" feature, which would allow me to create a shader that could be applied as a render pass, like a post process, which would be the best way to go about doing this in hindsight.
Not knowing how to do that, past me came up with a funny little trick to achieve the same effect:
I created a plane, attached it as a child object to the camera of the character controller, and applied the shader to a material straight into the object itself, and made it transparent. The player never sees outside of the plane, effectively making it a pseudo "full screen effect".
A technique I reused a bunch of times in this project was the "flip book". I created a texture atlas with even spacing between each of my desired frames of animation, then drew in photoshop. In unity, I created a shader which using the time node, gradually shows each specific part of the texture atlas, making it seems as though it is animating. The most apparent examples of this were for both paintings on the walls as well as for the character's faces. Below is a sample of a character's face atlas texture:
I really enjoyed this solution because of how simple and replicable it is, and I used it everywhere for lots of different purposes. Plus, it saved me from having to come up with a complicated facial rig for the characters to animate facial expressions.
Another advantage of using this method was that it allowed me to randomize the facial experession texture for each character's face automatically, saving me from manually having to change it one at a time. I did this simply by exposing the texture property from the shader, then made a small script to access said property and set it to a randomly picked texture from an array of textures:
I modelled, rigged and weight painted the NPC's body in Blender. This was one of my first times ever actually 3D modelling a humanoid - hence the abysmal topology ;) - which is deliberately low poly with optimization in mind, since I knew there would be loads of NPCs on screen, each animating at the same time. It has merely 25 bones and 495 faces.
Technical aspects asides, the model itself is not the prettiest nor most complex, but it was not without thought. I did it this way with the idea of not really focusing in the model itself, rather for it to be more coherent with the rest of the game's aesthetic. Namely, the low poly works well with the myriad of post processes, as you can see each individual face being affected by the light, which in the case of this game works well to create silhouettes as highlighted here:
A collegue in uni remarked that these models sort of remind them of the enemies in Superhot, which made me happy because that game was indeed one of the visual references I drew for making this game.
I also animated the characters in Blender myself. There are a total of 10 dance moves, and they are pretty simple loops which repeat endlessly, below are some examples:
There are 2 small scripts which I added to each player character in order to make the animations a little more interesting.
Firstly, it used to annoy me that I could see the crowd's animation in a repeated identifiable pattern because each animation loop would start and end at the same time, causing multiple NPCs to look identical in their dance from far away. So I made a simple animation offsetter, which at the start of the game, waits a random range between 0.1 and 1 second to start playing the looped animation. Below is the before and after, and it made a good deal of difference to ensure the crowd felt more organic:
The second script makes it so the character dances while always look in the direction of the player as they walk around. It's super simple, but it was quite effective at giving off the feeling that you are being watched and judged when you are walking around the space of the night club.