Solus: 2.5D Character Control & Footprints

The protagonist (we never came up with a name for her) moves along a 2D plane in a 3D environment, with generally realistic platforming movement inspired by Flashback: The Quest For Identity.  The system uses the Unity physics engine, manually controlling the character’s momentum to create grabbing and climbing, and adds quadratic drag for “crunchier” falling per Bennet Foddy’s 2015 GDC lecture. I started by modifying an existing character control script, the final system ended up a complete rewrite.

Character interaction is controlled with Layers. If an object has a Collider and is in Layer “Walkable,” the protagonist can traverse it, including ledge grabbing when appropriate. Rope climbing is the same, only with Layer “ClimbableRope.” (Wall climbing was also implemented, but cut for time.)

Want to play with it? You can download the Unity package here. Feel free to use the controller scripts & prefab setup for whatever you’d like (but not Anastasia Jacobsen’s cute character model please!)

Footprints are based on the method used in Röki. At the animation frames of the walking and running cycles where the foot first makes contact with the ground, an animation event is called with a boolean indicating left or right foot. A Projector Prefab with a Normal Map Texture is then instantiated at the location of the foot’s Bone. The Prefab has its own script, which fades the Normal Map out over 10 seconds, and then self-deletes.

The Solus demo is available on to download and play on Itch.io (Mac & Windows).

Solus: Lighting Up the Desert

Anastasia Jacobsen’s concept for Solus is an attempt at a semi-hard-sci-fi take on Alex McDowell’s “Planet JUNK” collaboration. The Earth has somehow stopped rotating, creating a 6 month summer/winter cycle and migrating the oceans away from the equator.

Logo art by Anastasia Jacobsen

In the demo, the player journeys down into the sand-buried remains of a skyscraper looking for water. For visual interest (and irony) I suggested the Futurist city of Brasilia which went over well with the team: Niek Meffert, Anastasia Jacobsen, Rosa Friholm, Ida Lilja, and myself. I was Technical Artist and Lighting Designer. (Solus was the first of two Planet JUNK collaborations. Many lessons learned were later applied to Shrooms.)

Solus uses Unity’s High Definition Rendering Pipeline (HDRI), allowing a wide variety of realistic volumetric effects—the simulation of light’s interaction with microscopic particles suspended in air, like smoke, water droplets and dust.

Desert scenes may never escape from Journey’s long shadow…

Topside, the lighting is very simple. There’s a Directional Light (sun) and not much else. Fill lighting is created by Global Illumination from the skybox. Blowing sand is created with the Unity VFX Graph. A number of post-processing effects are added, including Bloom, Tonemapping, Color Curve adjustments (for a more cinematic “desert” look) and a custom sparkle shader in the brightest areas. A faint volumetric Fog pervades the scene, to create a dusty atmosphere. Slightly behind the main plane of action, a second “thicker” Fog Volume is added, faded from bottom to top, to make the background distances appear greater and create a Bryce-like height fog effect.

Thank you, anonymous graffito

The underground lighting is primarily driven by a Point Light attached to the character’s lantern. The Volumetric Fog is thicker, increasing with depth into the buried skyscraper. An extremely bright Spot Light shines in through the entrance, volumetric and colored bright blue to contrast with the warmer lantern light. A similar, very narrow bright blue Spot Light shines down from the top of the first elevator shaft, as if a tiny stab of sunlight were blazing in through a chink in the roof. Farther down, mushrooms glow with an eerie green Emissive Material, casting light onto their surroundings via covert green Area Lights.

The theatrical darkness demanded that a final Light be added, to only be activated while editing the scene—literally named “Work Light.”

The Solus demo is available on to download and play on Itch.io (Mac & Windows).

Shrooms: HDRP in URP

The Shrooms demo runs on Unity’s mobile-friendly Universal Render Pipeline (URP), which doesn’t support volumetric fog and lighting like the High Definition Rendering Pipeline (HDRP). An early design decision was to lock the camera to only about 20 degrees of rotation off the default view axis. This allows many computationally-inexpensive (oldschool) cheats and tricks to create rich atmosphere. My mantra was: “HDRP in URP.”

Lighting

 In the Shrooms world, lightbulb is a job. Every light source is a glowing, bioluminescent mushroom person. The Copenhagen-inspired strings of street lamps that draw the viewer through the level each contain an animated Bulb Guy (created by Niek Meffert) sitting in a little wire gondola underneath a beat-up reflector. It’s a living.

He/she, and the remainder of the lamp, are set to not cast shadows, and contain a downward-facing  Spot Light. There are 37 in all, in addition to a wan Directional Light sun from the left—which is a problem, because Unity’s URP has a hard limit of 8 lights per mesh. The Unity Terrain tool splits the ground into a couple dozen smaller tiles, but the initial result was most of the light sources being simply ignored by the ground mesh, and glows often visibly sliced off where they crossed tile boundaries. Baked Lightmaps and realtime lighting in URP both share the lights-per-mesh limit.

Quick & dirty normal map in Photoshop: Filter > Other > High Pass, Filter > 3D > Generate Normal Map

The solution was to place pieces of flattened human-world junk along the ground, to disguise the boundaries and ensure that every light creates a visible effect. The junk shader uses a Texture stitched together in Photoshop from derelict building photographs, with a rough Normal Map.

Like the noise functions, the Texture is applied in World Space, allowing the same low-res crumpled square of debris to be recycled, stretched and resized ad-nauseum, with the Texture remaining undistorted and matching up perfectly at object boundaries. I’ve been a big fan of using world space shaders to create visual variety in instanced models since The House of Time–which, yes, will finally get some big updates this summer.

Simple exponential-squared Distance Fog ties the effects together, creating additional depth, and a Bloom post effect softens the edges of windows and other bright objects to match. A Depth of Field post effect further softens objects in the extreme foreground, adding to the murky intimacy, and the deep background is a hand-painted backdrop by Natasha Beck in an Unlit Shader.

HDRP in URP: A mix of simple, oldschool tricks and modern GPU-driven effects.

Faking Volumetrics

 It’s a not-so-dirty not-so-secret that even in high-end film compositing software volumetric lighting is faked by slicing the camera’s Z-axis into stacked, transparent planes at render time. This is what Shrooms does manually. Using the limited camera view and careful placement, patches of fog are created with a shader on a small stack of transparent planes. The shader multiplies a half-circle gradient alpha Texture with a procedural noise function. The noise slowly migrates up the Y-axis, as if mist were rising off the swamp. The noise is generated in World Space, so that scaling, squashing or stretching the fog planes creates no distortion to the noise pattern.

Light glows work the same way. Each light fixture model contains a set of three  planes: Two larger, colored, more transparent ones in front and back, and a smaller, more opaque, white plane in the center. The alpha Texture is a narrow cone gradient, aimed downward, and the World Space noise function slowly falls, like misty drizzle. The bright spotlights in the arena and cafe are just variants on this scheme, and a circular glow is used in a couple of additional spots.

Shrooms: Color & Forms

In Niek Meffert’s concept for Shrooms, giant mushroom people battle giant plant people in their swampy homeland, while grinding the remnants of humanity under their figurative boots. The dev team was Meffert, Lucas Oliveira, Sabrina Christiansen, Kaspar Dahl, Natasha Beck, and myself as Lighting Designer and Technical Artist. You can check out the demo (Mac & Windows) on Itch.io here.

Frequently heard during environmental modeling: “It’s good, Sabby. Get rid of the straight lines.”

The objective was to create a bright, colorful, murky, fungal setting. Fungus suggests bright, “sickly-sweet” tertiary colors, and we wanted an organic, lively scene. However, with too much clashing color the scene would have become busy and unreadable. Just finding your way and knowing what to interact with would have meant a frustrating cognitive load.

For that reason, I worked with the team to enforced certain rules to control user attention. The main character is in complementary colors. The bad guy’s color palette is a high-saturation split complement. NPC characters each have a single, dominant color. Non-interactive parts of the scene favor muted, analogous colors.

Lighting rules were also held to. Unimportant parts of the level fall back into mist and shadow. The character path is comparatively well lit, always suggesting where the player can and can’t go. Interactive parts of the scene (usually just-for-fun destructibles) pop comparatively, while others harmonize.

Forms avoid straight lines, with blobby, asymmetrical and impractical shapes but—importantly—recognizable outlines. Classic Warcraft games, and the art of Chris Sanders (Lilo & Stitch) were strong references here.

And of course, what’s the point of a game without asshole physics?

Oh Steam…

Kubrick twist: Searching Steam aliases is notoriously broken! This seems to be a known issue that’s been causing consternation for half a decade. Specifically, aliases with trailing numbers (e.g. spacetoast123) are unfindable with the exact string, and usually with a partial string.

So, while I’ve been able to send a friend request to the Second Prize raffle winner ($25 USD), who has no trailing numbers, nothing I’ve tried has brought up profiles for the First and Third Prize winners ($75 and $25, respectively).

If you entered the raffle, and your Steam alias ends in numbers, please friend me via my public profile page: https://steamcommunity.com/id/rhinocrate/ Over 300 hours of Civilization VI? Yes, it’s a problem. Regardless, you may have already won! I promised not to post handles publicly (and creating a duplicate with the same alias seems quite easy) so winners can’t be directly announced.

Bottom line: If you ever run a stunt like this yourself, even though it might make you look spammy, get an email too.

Raffle Code

As promised, I’ll be raffling off one $75USD Steam digital gift cards, and two $25 cards shortly. Just to be super transparent, here’s the raffle code.

And no, I’m sure mathematically this wouldn’t hold up in a real lottery–but for a raffle with fewer than 20 valid entrants, I think we can call it good.

function rankRaffleEntrants(){
        var entrants = "Prima Secunda Tertia Quarta Quinta Sexta Septima Octavia Nina Decima"; //Steam handles
        entrants = entrants.split(" ");
        ol = document.getElementById("orderedList");
        //print function
        function addToList(entrant){
          var li = document.createElement('li');
          var nextInList = document.createTextNode(entrant);
          li.appendChild(nextInList);
          ol.appendChild(li);
        }
        while (entrants.length>1){
          var pick = Math.round(Math.random()*(entrants.length-1));
          var entrant = entrants.splice(pick,1);
          addToList(entrant);
        }
        addToList(entrants[0]);
      }

Basilicum on Reddit – Raffle Extended!

Within the hour, I’ll be posting a Unity WebGL game to Reddit, in hopes of collecting a statistically meaningful sample of responses to a questionnaire. In addition, through Tuesday, June 8 at 22:00 CET I’m conducting a raffle to encourage participation. This could go wrong in so many ways, and only right in one.

The characters’ anxious hand-wringing is my own.

Edit: The raffle is open! Click here to play the test app.

Performs best in Firefox and Chrome. Feel free to play the game as much as you’d like, but please only submit one survey form.

Terms and Conditions:

Persons over 18 who submit the survey between Friday, June 4 at 22:00 CET and 22:00 CET Tuesday, June 8, and enter a valid Steam profile name will be eligible for a raffle, to be conducted by June 20th, 2021.

-One first-place winner will receive a $75 USD digital gift card, sent through Steam.
-Two runners up will receive $25 USD digital gift cards, also sent through Steam.

The winners will receive a friend request from my Steam account, “rhinocrate” and receive their digital gift cards as a friend-to-friend gift.

I wish it weren’t necessary to say, but I must reserve the right to disqualify participants based on evidence of ballot-stuffing or other forms of inauthentic or abusive behavior. There is a limit of one entry per person. Steam accounts must have at least one purchased game to be eligible for the raffle. If fewer than 20 valid responses are received, the raffle will be cancelled. No data collected will be used by me or anyone else for any purpose beyond tabulating results and completing the one-time raffle, nor will personally-identifying information (including IP addresses and Steam account handles) be distributed.

Hacking Twine: The Multiplane Effect

For Chronovoros, I created a Twine hack using custom macros inserted via Chapel’s Custom Macro Framework. These interact with the game’s custom CSS styling by adding foreground and background image elements. The image files,  indexed-color PNGs with a 1-bit alpha channel, are crushed down to surprisingly small file sizes for their resolution. (GIF would be just as useable, with interesting implications for animation.)

A layout for the different planes of one “scene” in the game, color-coded

Each set of images has its own macro, which when called passes a list of the desired image filenames and styling to a function which displays them. The images are scaled to fit the width of the window, and positioned to align either their top edge to the top of the viewport (the entire scrollable content of the page) or their bottom edge to the bottom of the window. An additional function is called every time the window paints (started by a call to its own macro on the first page of the game) which adjusts the vertical positions of the planes based on user scrolling; the vertical positions are calculated so that whatever the height of each individual image, scrolling completely from the top to the bottom of the window displays the entire image.

In practice, the multiplane hack breaks when the window is too tall. An aspect ratio should really be enforced with some kind of letterboxing scheme in the CSS. Having to write and call an entirely new macro for each set of image planes, while not complicated, is a little inelegant for a production-ready tool. Additionally, HTML5 special effects like contrast, color adjustment and blurring are implemented, but didn’t end up used on Chronovoros. Knocking the multiplane hack into something easier to use would be a good weekend project, for a later date.

Click here to download demo files and code for the Twine Multiplane Hack.