Ryze

A 2D precision platformer about climbing by throwing yourself, made by Idomi Games, the studio I co-founded. As a programmer on the team I focus on how the character feels to control and on the mechanics the levels are built from.

Unity 6 · C# · 2022 — present · Steam playtest out now

Steam page itch.io

One verb, done well

Ryze has a single movement verb: charge a throw, release a pearl, and teleport to wherever it lands. The character controller runs on a small state machine (grounded, aiming, pearl in flight, respawning), and a lot of care goes into the moments between states. A press just before landing is buffered, so it still counts. Walking off an edge turns you into the pearl instead of dropping you. Probes under each foot notice when you are teetering on a ledge, so the animation can react before you fall.

The pearl bounces off walls and rolls down slopes, and on long throws the camera hands over to it, so the player never loses sight of where they will land.

A long throw: the camera follows the pearl up into the next area

Charging the throw

Holding the button charges the throw for more height, up to a cap, and the throw goes off by itself when the cap is reached or the player starts to fall. Readable code for the core loop matters: this is the part of the game that gets tuned the most.

if (PlayerInput.Shoot.WasPressedThisFrame())
    shootPressedAt = Time.unscaledTime;

// A press shortly before landing still counts.
if (CanShoot && Mode != ShootingMode.Aiming
    && PlayerInput.Shoot.IsPressed() && HasBufferedShootPress)
{
    shootPressedAt = float.NegativeInfinity;
    chargingFX.ChargeShot();
    Mode = ShootingMode.Aiming;
}

if (Mode == ShootingMode.Aiming)
{
    aimTime += Time.deltaTime * buildUpSpeed;
    if (IsFalling || PlayerInput.Shoot.WasReleasedThisFrame()
        || aimTime >= maxBuildUp)
        Shoot();
}

A test level for every mechanic

Every mechanic I add gets its own station in one long technical test level. A change to the controller can be checked against all of them in a minute, and designers see each component working on its own before they use it in a real level. Each one is a self-contained component, tuned from the inspector.

Time bubbles are one of them. The character, the pearl and the pistons each run on their own timeline (built on the Chronos plugin), so a bubble changes the speed of everything inside it: movement, physics and animation slow down or speed up together.

Short, medium and fully charged throws
Walking through a bubble that doubles time, then falling through one that halves it
Walking against a conveyor belt, then with it
A crumbling platform gives way, then rebuilds when the world shifts between light and dark

Recorded in the test level. Other stations cover moving and slippery platforms, pistons, dialogue triggers, area banners and Japanese text.


A dialogue system that travels

I wrote this dialogue system for an earlier project and brought it into Ryze with its core unchanged. Three decisions made that possible:

  • It knows nothing about the UI. Each line goes out as a Ripple event. Every NPC listens and shows its speech bubble only when the line is theirs and the player is close, and the dialogue sounds listen to the same event. A new project only needs a new view.
  • The caller decides when a line moves on. Starting a dialogue is one awaitable call that takes the condition for advancing. Trigger zones, walk-up cutscenes and lines that react when the player keeps failing at a checkpoint are each a small component around that call.
  • Dialogues are data. Writers edit lines and speakers as assets in the inspector, and every line has a localized version that falls back to the English text.
An NPC conversation in the game

Built on Ripple

Game state in Ryze runs on Ripple, my ScriptableObject framework: the player's visibility, the camera target and every gameplay event are assets. Systems stay decoupled, and when something goes wrong in a playtest, the inspector shows who changed what.

The pearl bouncing off walls on its way up

Made by Idomi Games: Tristan Metz (programming), Arjen de Aldrey (programming), Canozalez (level design & writing), Chaos-1001 (art) and Pierre-Henri Barralis (music & audio).

← Back to the portfolio