Home Game Development Optimizing the visuals of I Was a Teenage Exocolonist

Optimizing the visuals of I Was a Teenage Exocolonist

Optimizing the visuals of I Was a Teenage Exocolonist


Game Developer Deep Dives are an ongoing sequence with the aim of shedding gentle on particular design, artwork, or technical options inside a online game with the intention to present how seemingly easy, elementary design selections aren’t actually that straightforward in any respect.

Earlier installments cowl subjects such because the technical design of inconceivable areas within the M.C. Escher-inspired recreation Mind Palace, the transition from digital illustration to indie improvement with comedian e book author and artist Meredith Gran of Perfect Tides, and designing and implementing controls for the cellular port of PC and console title Descenders. In this version,  Sarah Northway, co-founder of Northway Games and creator of I Was A Teenage Exocolonist, shares with us some visible suggestions and methods used to take the sport from Unity prototype to full console launch.

Taking a recreation from Unity prototype to Switch and PlayStation can
contain compromises, however what you want most are some good methods and
customized shaders. Our narrative deckbuilding RPG I Was a Teenage Exocolonist
is ready on the alien jungle planet Vertumna, which you run round and
discover as you develop up. I used to be nonetheless attending to know Unity after I created
these out of doors scenes, and errors have been made. But over 5 years, I
realized easy methods to make our complicated out of doors scenes quick and environment friendly.

I’m Sarah Northway, co-founder of Northway Games and creator (/designer/coder/co-writer/artwork director) of I Was a Teenage Exocolonist, in addition to the narrative city-building sequence Rebuild
and different video games. I could be finest recognized for touring the world with my
husband for 5 years after we first went indie. It was the jungles of
Central America and the coral reefs of Southeast Asia that impressed Exocolonist’s lush landscapes and concentrate on the pure world.

Exocolonist Glow Season Concept Art by Sarah Webb

To deliver this world to life, I labored with idea artist Sarah Webb, illustrators Meilee Chao and Eduardo Vargas, and 3D modeler Sarah Roland on our stunning out of doors scenes.

Quiet, Pollen, Dust, Wet, Glow

In the principle colony area, all of the vegetation, terrain textures, and climate results change with the season. Some vegetation have yearly lifecycles, rising taller or flowering then returning to buds. 3D components like rocks and colony partitions are tinted to match the climate, which incorporates rain, snow, warmth shimmer, and clouds of pink pollen.

Our seasons have cute names (Quiet, Pollen, Dust, Wet) however are roughly equal to winter, spring, summer time, and fall. There is not any evening cycle, however through the fifth season, Glow, Vertumna’s two suns are beneath the horizon for a number of weeks. During that point, nature comes alive with firefly-like particles and light-emitting vegetation.

The 5 seasons of the planet Vertumna

Exocolonist’s lighting is flat with solely painted-in shadows, no regular maps or specular sheens. I used the built-in render pipeline and ahead rendering to layer a whole bunch of semi-transparent Sprite-based vegetation. The Terrain makes use of a tri-planar shader and swaps its TerrainLayer textures when the season adjustments. 3D rocks have mushy gradients utilized based mostly on their orientation, and vegetation and different 2D objects are billboarded to face the digicam. The total impact is that of a portray come to life.

During Glow season, the colony gates shut, characters disguise indoors, and the lights come out, all toggled by Components that allow or disable little one objects based mostly on the season.

There. Are. 1,600. Lights

Here’s the place issues bought sophisticated. Some vegetation emit gentle in Glow season: the bobblesprouts, mushtrees, and gnarlwood. Naively pondering “Unity will handle this for me,” I initially simply embedded level lights into each plant prefab, which I toggled on or off based mostly on the season.

The end result was 1,600 lights in a single scene, as much as a thousand at a time within the digicam’s area of view, all affecting one another, the bottom and the participant. It was superb.

Original Glow prototype with over a thousand lights

Glorious and gradual. I cranked the concurrent pixel gentle depend to twenty for screenshots (default for “Fantastic” high quality is 4). The scene above was performing 6,000 draw calls per body, most with a number of lights, and ran at roughly 1 fps on my goal low-end PC.

Batching Plants Blanches Pats

Let the optimization start! I thought-about Unity’s software for including grass sprites to Terrain, however I couldn’t get the management I wanted. Instead, I dove into customized shaders and ready to batch the plant draw calls by tossing their artwork into an Atlas collectively.

I wrote editor instruments to position quite a lot of vegetation in an space without delay, clumping based mostly on species parameters, avoiding duplicate artwork too shut, and randomizing their angles and sizes. Then I tweaked them by hand to compose little vignettes.

Some vegetation wave, others breathe or bounce

Every plant is a person object within the scene, rippling, bobbing, and bending when the participant walks by means of it. Some species swell up and appear to breathe, exhibiting the skinny distinction between wildlife on the planet Vertumna. But all of them use a single materials, and as much as a thousand may be rendered with a single forward-pass draw name.

To do that, I used a customized vertex shader based mostly on Unity’s default Sprite shader. Unity threw a wrench in by not supporting customized materials property blocks on SpriteRenderers, so I handed the values I wanted to calculate plant motion by means of the unused RGBA channels of SpriteRenderer.coloration. I used to be concurrently horrified at my horrible hack, and happy with how environment friendly it was.

Shader programming in a nutshell.

Batching took scenes down from 6,000 draw calls to about 6. Next, I eliminated the Light elements from the plant prefabs, and eliminated Unity’s lighting from the vertex shader. I wouldn’t want these the place I used to be going.


I finished tinting the vegetation black through scene lighting, and as a substitute I baked the tint in utilizing Photoshop. Only the light-emitting elements of the vegetation are absolutely coloured, and a murky fog tints distant ones. Then I began including post-process results.

Everything appears higher with Bloom and HDR, it’s a reality. I pushed it too far, then introduced it again one notch. This gave the bobblesprouts and mushtrees the impression of emitting gentle into the world round them. And the geodesic greenhouses look fab.


HDR porting gotcha: We had a difficulty on the Nintendo Switch with our post-process highlighting impact, which attracts a glowing define round interactive objects once you’re close to them. We have been utilizing the alpha channel to retailer hidden information in regards to the edges of objects, however with HDR enabled, the Switch ignores alpha throughout post-processing to save lots of bits for the R, G, and B channels. To repair this we needed to disable HDR on Switch, then alter for the lower-bit alpha (even with HDR disabled, alpha is capped to 1). Luckily this was our solely tough rendering challenge throughout porting.

Bake it Till You Make It

For the greenhouses and spaceships, I used an emissive texture map to layer additive gentle over an everyday texture. Exocolonist’s 3D objects all use the identical customized floor shader which incorporates Unity lighting, with mushy Lambert shading and few shadows. But quite than render most lights on the fly, I switched to Unity’s baked lighting system.

After taking all 1,600 lights out of the vegetation, I nonetheless needed key areas of the bottom and buildings to be lit by glowing flora. So I added again in baked lights right here and there, matching the vegetation’ glowing colours. I did the identical for the synthetic lights on the colony partitions and beside doorways whereas I used to be at it. Only a couple of watchtower spotlights are nonetheless realtime, to allow them to illuminate the participant and different characters transferring underneath them.

Prototype (left) versus Baked lights (proper)

The Baked Lightmaps system creates textures based mostly on gentle positions that may later be additively utilized to 3D objects whereas the sport is working. As common with optimization, I used to be buying and selling elevated ram (3-5 further textures in reminiscence per scene) for sooner processing time. What made this potential was utilizing Addressables to retailer most of our artwork within the filesystem when it wasn’t getting used.

One catch: lightmaps needed to be disabled when the seasons modified. I added a part to 3D objects which remembers their Renderer.lightmapIndex and units it to -1 when not in use.

The Lightbearer

The floating particle results simply labored; they’re mad environment friendly out of the field. My solely optimization was to make their world-space emitter a restricted measurement quantity that follows the participant round.

But the participant character nonetheless wanted one remaining contact: a dynamic gentle they “hold” which illuminates the whole lot they stroll close to – floor, vegetation, constructions, and characters.

The ParticleSystem utilizing a texture sheet and noise turbulence

I performed round to seek out an environment friendly means to do that. Since the vegetation already knew the participant place to have the ability to bend out of their means, I used it to calculate the sunshine in my vertex operate:

<p>o.participantLightColoration = fixed4(1, 1, 1, 1);
if (_IsGlowSeason) {
    float3 playerWorldPos = _PlayerPos.xyz;
    float3 vertexWorldPos = mul(unity_ObjectToWorld, v.vertex);
    float distToParticipant = distance(vertexWorldPos, playerWorldPos);
    float lightRadius = 3;
    float lightPower = (lightRadius - min(lightRadius, distToParticipant)) / (lightRadius + 0.001);
    o.participantLightColoration = fixed4(0.82, 0.80, 0.73, 1);
    o.participantLightColoration.a = lightPower * 10;

The participantLightColoration is then added in per-pixel through the fragment or floor methodology. I replace _PlayerPos through Shader.SetGlobalVector because the participant strikes, and _IsGlowSeason when the season adjustments.

The Result?

Well, it’s a complete hecka-lot sooner now! Glow season is a easy 60fps on most techniques.

I used to be able to must rewrite the reflective water shaders or downres our textures to 2k for Switch, but it surely didn’t come to that. Once Glow was settled, most of our porting woes concerned controller help, ugui menus, and save timing. Oh, and being pressured to improve Unity on the eleventh hour (you’ve been warned!).

Enjoying Glow Season along with your buddy Dys

If we ever port to cellular, I’m certain I’ll revisit a few of these selections and discover extra methods to scale back GPU cycles and lighten the load in ram. But I’m proud that Exocolonist has come to date, from “let’s throw a bunch of lights together hey that looks cool” to scenes which are engaging, constant, steady, and quick.

I Was a Teenage Exocolonist is out now on Switch, PS4, PS5, and PC/Mac/Linux.



Please enter your comment!
Please enter your name here