Coastal World — Case study

Merci-Michel ®
11 min readSep 26, 2022

--

A whole new world that connects neo-banks together to serve communities.

Context & story

What do banking and video games have in common? You’d probably say not much and you may be right… but when Coastal Community Bank came to us to create something that didn’t seem usual, we were intrigued and excited. It was the first time we had new business popping up from a Twitter DM ;). Sometimes great projects can come from anywhere. At this moment we had no clue we were going for a 6 month journey with them.

Coastal World is a showcase of Coastal Community Bank’s partnerships with fintechs & neo-banks, all powered by Coastal’s BAAS (Bank as a Service) solutions. The main goal of the project is to teach users about digital banking literacy in a cool way and connect consumers with innovative and community-driven financial solutions.

At Merci-Michel, we like to blur the line between web/digital marketing and video games. We believe gamification is a fantastic toolset to engage users and to communicate all sorts of messages in many different cool ways. This project was a perfect playground for us to apply our vision.

Some early 3d mockups we did

Mechanics & logics of the experience

Each fintech partner is represented on the archipelago and offers different quests to be completed and rewarded by coins and a system of collectibles.

The Coastal World archipelago

You must complete certain missions to progress and unlock accessories such as the jetpack (i.e. flying backpack) or the fire shoes. With those, you’ll look cool and move quicker around the islands.

There are plenty of accessories to unlock to customize your character. Don’t forget to wear your jetpack to go faster!

Most of the brand content is delivered by NPCs (Non-Playable Characters) through short dialogs. Way more efficient and fun than having the user read some big text paragraphs.

Each user has different needs regarding their finances. For that reason, we built a custom user path to highlight specific content of the experience, according to their interests and values. The user’s progression is always saved in the local storage of the web browser. This way, the user can come back later, at the very same state, no need to start all over again!

It’s alive!

We wanted the player to feel the liveliness of the environment: a lush archipelago, populated by friendly inhabitants, with many places to explore and things to do.

Here are the first sketches of the characters
And the final ones

Each character has its own look and personality. We built an NPC customization module to generate their geometry with different colors and accessories, on load time. From the editor, we can also assign navigation parameters to each one of them: they can run, randomly, walk in the park, follow a path on the streets…

Chatting with NPCs is a key component of our gameplay. With that in mind, we invented a singular language, where each word produces specific “phoneme” sounds, depending on its letters. We also considered punctuation marks, to add pace and realism to the dialogs. Each NPC is different; some have a high-pitched voice and others have a lower-pitched one.

We also added emotes to our dialog system. Each dialog bubble can trigger NPC animations, making the reading experience more fun and engaging.

NPCs remember you! When you speak to them again, they welcome you back.

To add even more life to the islands, we added spatialized sound : you can hear the waves near the sea, the birds singing in zones with dense vegetation, or hip-hop beats when you get closer to speakers!

Ambiances are set directly from blender using our editor plugin.

Navigation, controls & camera

You can use your mouse, trackpad, keyboard, or touch if your device allows it. We’ve even mapped our custom arcade cabinet, to target as many users as possible!

On mobile, we decided to design a one-button controllable handheld experience. We use portrait mode to make it more natural and avoid “hacks” to solve the in-app web view issue that blocks the device orientation. As the aspect ratio is very different from the desktop version, we adjusted the camera position and the field of view, to offer more comfort to the player.

To deal with the corporate content, we imagined a virtual smartphone inside the website, in which you can find all the information you need. It also serves as a second navigation; you can teleport anywhere in the archipelago by clicking POIs from a mini map, you can customize your character, and watch your progress. In fact, it’s nearly a website inside the website.

Initial virtual phone wireframes
Final version. Fun fact: the hand color matches the character’s skin tone of the user

Capturing user’s attention

Wandering into a 3D open world is not always easy for the average user, and we don’t have much time to get their attention. To solve this problem, we built a notification system inspired by smartphones’ UX, to guide the user through the world. So, at each step, if the user is a bit lost, we encourage them to access the map or guide them to a specific mission.

We also created a system of icons, placed above the interactive elements in the 3D. They indicate to the player the available interactions. Important items such as “quests” or “fintechs’ ambassadors” have a more visible icon. Each icon automatically expands when the player is getting close by and can perform the interaction.

DOM optimization

All UI animations are strictly made using CSS (animations & transitions). There is no tween library in the project! The main advantage of using CSS Animations is that they can run off the main JS thread on mobile devices, where every bit of performance improvement matters. Even if WebGL is slowing down the main thread, the user interface always stays fluid. It can even reach 120 Hz on an iPad Pro with pro motion capabilities!

Plus, there’s a beneficial effect to this: CSS animations consume less battery power than JS animations.

The hand animation is only made of manual css keyframes and svg to manage the different colors.

Blender 3D pipeline

A multi-file workflow

Each scene and group of assets are in separate files to reduce conflicts when multiple designers work on the project at the same time.

All assets are then imported onto scene files using a blender link. Dynamic links allow us to build and iterate on island designs quickly and efficiently: each asset update is automatically reflected on island scenes.

Assets files of each category and material assets are all dynamically imported in a level design file.

Using Blender as a level editor

All the level design is done directly in Blender. We heavily rely on the new asset browser feature from blender 3 : you can create levels by simply dragging and dropping assets and NPCs onto the island!

We then coded a custom Python UI extension to quickly export all elements and see updates on the development server. By having our talented 3D artists test their designs in the real WebGL project, we’re able to quickly iterate on the visual rendering and level design, making sure that our final product looks as good in the browser as it does in our heads.

Our editor can export static props, scripted entities (NPC, interactive buildings), navigation paths, audio area… Depending on object type, it will be exported as a GLTF file or as a plain object in a JSON manifest.

Demo of our Blender editor plugin

Rendering

Terrain Rendering

Because scenes are quite large, it was important to have visually rich island surfaces. Baking a full island texture wasn’t an option : it would produce a hard-to-maintain, blurry and heavy texture.

We chose to use a technique called texture splatting. On Blender, we painted a “splat map”, using the red, green, blue and alpha channels. Our terrain shader will then map each color channel to a specific terrain color and tile texture.

To add even more variety to the terrain, a noise is applied to create small color nuances on the surface. The island’s height also influences sand color. Finally, we use another noise texture to create fake projected moving clouds to add a bit of life and movement.

Water Rendering

Coastal World takes place on an archipelago, so a good looking (and optimized) water was very important. We chose to separate the water render into three components.

A water surface shader, on a big plane around the island : it’s just a set of noise texture samplings and some smooth steps between them to create the two water patterns. Subtle color variations are added to avoid a boring single-color sea on the horizon.

A foam / underwater effect, directly in the props and terrain shader. It’s basically a fog effect: the mesh color fades to the water color the further it is from the surface. Near the surface, a small white band is added to mimic a foam effect. We also added a “wet” effect that follows the water level variations.

The underwater effect on the assets, with and without the skybox.

Walking waves and water drops are done using our particle engine.

Grass Rendering

Grass was also an important visual element on the island. It adds movement and passive interaction when the player walks on it. Grass also helps to break up the long vertical lines of the buildings (one of the downsides of the low poly style).

The grass animation when you walk on it is simply two delayed uniforms of the player position — there is no GPGPU here!

We use the same approach as Bruno Simon’s, so go check out his awesome thread for a full technical breakdown. One of the differences was that we precomputed the island’s elevation in a simple one-channel 8bit texture, since we didn’t need the improved height precision. The designers also painted a “grass texture” to choose where the grass would appear.

Left image: the “grass map” texture. It combines the island elevation and the areas where the grass can grow.

Optimizations

Heavy use of merging

3D assets like rocks, trees, houses, are reused a lot in the level design. Instead of exporting a huge GLTF containing all assets and island geometry, we can export a GLTF containing only island geometry and coordinates of all assets. We then build the island at load time with our load pipeline :

  1. Load the island JSON manifest containing the list of needed assets
  2. Load in parallel to the island .glb file, the assets coordinates, and the assets .glb files
  3. Merge all assets into chunks. Chunks are groups of meshes. They are used to cull parts of the island that are not visible.
  4. Cache merged islands chunks using the Cache API : further island loads will reuse merged output, leading to a sub-second load time!
We use an overdraw viewer shader to make sure our chunks are correctly sorted to avoid costly over drawings.

Merging all assets together doesn’t mean they have to stay static! We added an “FX Texture map” to the assets shader. Using the same UV set as the gradient atlas one, we can add custom behaviors to specific assets like toon-style glass reflection, wind effect on the vegetation, or floating effect on boats.

Physics engine

The physics is done using a simple Octree physics for collision and ray casting. All bodies (NPC, player, vehicles) are spheres to simplify collision tests.

To reduce pressure on the main thread, we moved the physics engine on its own worker. The worker contains code for terrain ray casting, NPC movements manager, player / vehicle controls, camera movements, and collision with the ground.

All static colliders are merged at load time. We created a layer system to toggle colliders for interactive objects like the broken bridge or the skatepark, without having to rebuild the Octree graph.

One of the last major optimizations we did was removing individual colliders and adding big walls around them instead. This reduces Octree generation time a lot and also adds better performance at runtime.

Lights and Shadows

We wanted visible shadows from afar, to increase the sense of depth and keep a visually rich world despite our texture-less low poly assets. We implemented a custom shadow rendering technique based on the Cascaded Shadow Maps. This approach allows casting shadows on a large surface by combining shadow maps of different resolutions, depending on the distance from the camera.

Since most props have only a subtle movement, we can bake a big static shadow map at load time and combine it with a smaller dynamic one for characters and assets that are near the camera. By doing this, we only have one additional render pass for the shadows instead of two.

The blue-ish shadows come from the real-time shadow map and the red-ish shadows come from the static shadow map baked at load-time. You can see the fade-in effect between the two shadows. Far away characters have no shadow because they are dynamic meshes that are outside the dynamic shadow area.

Post-Processing

Post-processing often takes a huge part in the frame budget, especially on mobile. Since we didn’t need super fancy effects, we chose to remove it completely. The vignette effect is done directly in CSS, so the vignette animation can run off the main thread. The animation of transition in overlay, is also a simple always-on-top scene, only rendered during the transition from one island to another.

Telescope effect is made with CSS to avoid relying on WebGL post processing.

Scalable quality at runtime

The experience had to look as good as possible while running smoothly on all devices, so it was important to adjust the quality depending on the user’s hardware. Nowadays, hardware detection is not super accurate because of Apple obfuscating GPU information. We chose a more reliable and future-proof approach by adjusting quality dynamically, depending on the current frame rate. On a regular interval, we downgrade or upgrade the quality preset depending on the average FPS.

Different quality presets. On “ultra”, you have a fully dynamic shadow and large grass area. On “very-low” there is almost no dynamic shadow, no grass, a reduced NPC render distance, and no effects on the water. The maximum canvas resolution also depends on the quality preset.

Final Words

Watch the teaser

Try it on: coastalworld.com (type a “Konami code” to unlock a surprise ;)).

Company info

Merci-Michel is a (french) digital gamification studio.
Visit our website: https://merci-michel.com
Follow us on Instagram and Twitter for more back stories!

--

--

Merci-Michel ®
Merci-Michel ®

Written by Merci-Michel ®

Interactive Design & Storytelling Studio.

Responses (1)