As the sole developer working on The Last Sprite, I was responsible for all Blueprint visual scripting. I’ve picked out a few pieces to talk about below. This article will cover:
Implementation of a rolling character
Implementation of machines destroyed/deactivated by buttons
Movement Statuses
Level sequencing & events
Rolling Character Implementation
In creating a rolling character, there were two main routes I could take. I could use a physics-enabled rolling ball that gets pushed around the map by directional force, or a 'fake physics' solution that simulates a rolling ball. I researched into implementation of rolling characters in Overwatch, The Eternal Cylinder, Super Monkey Ball, and Rock of Ages, and determined that a faked physics solution would be preferable.
A faked physics solution provides the player with the same level of movement accuracy as enjoyed in platformers with traditional walking characters, and removes the risk of unwanted physics interactions. The player character is actually implemented as a capsule component, and controls the same way as a walking character.
The ball of vines itself does not actually roll across the ground at all, and instead is rotated in accordance with the direction and speed of player movement to give the illusion of rolling. Attaching a box to the player helps demonstrate this implementation.
Machines & Buttons
The Last Sprite’s core gameplay loop requires the player to deactivate machines by ground slamming onto buttons. There are four machine-manipulating buttons scattered throughout the world, but the machines and the affect they have are varied:
Turbines - Explodes. Parts fly off.
Pumps - Slows to a stop. Glowing pink sludge drains away.
Gates - Lower to allow the player past.
Lifts - Activates to open shortcuts
There was potential here for some very messy blueprinting, but thankfully, I came into this project with a solution already in mind.
I created a single parent blueprint class called BP_MachineBase. Within this class, I created an event simply called ‘OnButtonSlammed’. I then created child blueprints for each machine type, overriding OnButtonSlammed in each child to create different responses to the associated button being slammed.
I then created the button blueprint. In this blueprint I created a variable public array variable of type BP_MachineBase. I created an event for when the button was slammed with a For Each Loop that would trigger OnButtonSlammed for every member of the array variable.
Then it was a simple case of placing my machines and buttons into the map, and filling the public array variable with the names of the machines it should affect.
Left: Machines connected via glowing cables to a button.
Right: Exposed arrays on the button actor showing links to all affected machines and cables
Movement Statuses
From the beginning of The Last Sprite’s development, I knew I’d have multiple forms of movement, including but not limited to walking, dashing, grappling, and slamming. I also knew that not all abilities and world events should be triggerable during all forms. For example, the player shouldn’t be able to perform a ground slam while walking or dashing, the player shouldn’t be able to spring while grappling or slamming, and all abilities should be disabled during cutscenes. I scripted with this in mind from day one. One of the first things I created as I began creating player abilities was an Enumerator containing the player’s different forms of movement. I could then use this Enumerator paired with a stored variable on the player (MovementType) to determine which abilities available to them at any given time.
Likewise, while my core production plan only included the implementation of a fire element, a project stretch goal was to add lightning and water elements. I worked with this in mind from the beginning, creating an Enumerator for element type. This required little extra time during initial production, but would save countless hours rejigging code if I decided to add the elements later.
Level Sequencing & Events
I used UE5’s built in level sequencing and level blueprints to create The Last Sprite’s cutscenes.
Some of these sequences were simple affairs where the player would retain full control but dialogue would be drawn onto the screen. These were triggered using simple box overlaps connected to level sequences; the level sequence then spoke to an in-level BP_DialogueManager that determined which subtitles to draw onto the screen for how long, and which voiceover lines should be paired with them.
A second type of scene took control away from the player and moved the camera. One of these was triggered at the beginning of the level, and the other when all objectives have been completed. These also speak with BP_DialogueManager, but also contain keyframes that trigger music, camera movements, camera fades, and more.
Comments