Link to Build
Skip To Section
Scrapped is a single player, third person, three-dimensional (3D) platformer incorporating environmental hazards and skill-based challenges developed for the personal computer (PC).
Scrapped focuses on utilizing magnetism-based mechanics to reward discovery and experimentation. In each level, players must evaluate their surroundings, determine their preferred pathway, and reactively jump, attract, and repel to their intended destination. Throughout their route, players encounter environmental hazards, one-step solution puzzles, and skill-based challenges.
Genre: 3D Platformer
Engine: Unreal Engine 4
Team Size: 14 People (2 Programmers)
Development Time: 5 months
Refined the core magnetism mechanic and character control based on player feedback
Implemented and refined six different magnet functionalities
Created an NPC that follows a spline and runs on triggered events (Fritz functionality)
Created the behaviors Fritz uses on triggers
General bug fixing and polish
The core gameplay mechanic in Scrapped is magnetism attraction and repulsion based platforming. Magnets determine their force direction based on 6 surface normals and where the surface normals are compared to the player. This force direction and the magnet's magnetic strength is handed to the player for the player to interpret the actual force to be applied to the player.
I was personally in charge of the magnetism mechanic after proof of concept tech, sometime through proof of concept gameplay and was the main developer working on polishing the feel and functionality, as well as, creating the different magnet types. The initial system was setup by our main level design scripter (Colton Revia) and the particles were handled by our particle designer (David Mershawn). It was my responsibility to make magnets function as expected from a player's perspective, make them fun, and handle the overall polish of them.
Main Ways Used To Alter Magnetic Behavior
Alter the positions and rotations of surface normals
Overload the find force function
Alter magnetic strength dynamically
Apply force directly to the player character
Example of a basic magnet inside a blueprint.
The arrows represent the surface normals and are referenced
for location and direction in calculations.
Example of the base implementation of FindForce. FindForce cycles through each surface normals, then Get Normal Distance From Surface calculates the force each surface normal adds.
Get Normal Distance From Surface logic:
return Surface Normal dot (Player location - Surface Normal location)
Wall magnets are one direction magnets and only work with attract.
The FindForce function zeroes out total force, effectively making the calculations done in the player not applicable.
In the overloaded FindForce function, three forces are directly applied to the player, one in the "negative z" direction, one from the player to the magnet, and the third and strongest force is in the forward direction of the magnet.
The way we implemented magnetism did not directly support diagonal magnets. In order to get the height to distance ratio for gameplay, we had to make certain altercations.
Tilted the "z surface normal" to increase the upward directional force
Increased the magnetic force strength of the magnet type
Added a trigger volume to apply force to the play to force them to the center of the magnet while repelling (dealing with a problem of magnets not applying forces well when the character was on the ground)
Swinging magnets have a dead zone of attraction underneith the magnet and have more attraction at the bottom of the effective range.
Normals on the magnet are shifted down to move the magnet's effective center where the player will be swinging.
The negative z and normal z normals are reversed in positions (the negative z is where the axis is in the image)
The goal of the slide magnets were to keep movement going forward.
The z positive direction was removed from total force to prevent the player from repeling "upward" on a wall magnet (player appeared to move up but was just maintaining the same z height in the world going down a 45 degree slide).
Made attraction stronger the farther the player was from the magnet and weaker up close (to prevent the player from getting stuck while attracting).
The z positive direction was removed from total force to make the upward direction more controllable.
When player is in a launch magnet's range, the player's velocity is capped (to allow the magnets to apply a predictable amount of force).
When the player is in range and repelling, launch magnets directly add force to the player in a forward upward direction of the magnet.
Slide Wall and Slide Launch Magnets
General Polish on Magnetism
Change Diffuse in Material
For both the player and magnets, modified their materials to change the colore of the white diffuse to be red or blue. Initially only the emmissive was changed, making the colors very difficult to see in brightly lit areas.
Material blueprint below. Red box indicates modifying the diffuse.
Modified Particle System's Interaction with Magnets
Initially the bubble particles around the slide magnets and the diffuse color of the magnets were not being changed by the same code. I moved what was in the magnet color change to the particle system. The reason for this was on the slide launch magnets, about half of the launch magnets would stay white while all of the bubbles would be red. It gives a better impression to the player that everything is working if the game is consistent.
The second major change to the particle system was to detach spawning particles from what we were doing with streaming. Depending how things were streamed in, particles would not spawn. I altered the associated blueprints to not spawn on streaming in, but when the player comes in range of the magnet. There was also the added benefit of smaller hitches when the player would hit a streaming volume.
Both weakened the attraction directly under the magnets while greatly increasing the attraction at the out edge limits under the magnets. Doing so both improved the swinginess of the basic magnets and also made recovering much easier.
Time Based Priority
To prevent getting locked between two magnets or pulled back onto the magnet the player is launching from, the time the player is in each magnets range is taken into account. The magnet that has been in range the least amount of time is the strongest.
The original design of the magnets causes repel and attract to be stronger the closer the player is to the magnet. This caused jumping and repeling to be weaker than just repelling. Extra functionality was added to make jump repel be much closer to just repelling.
The gif to the left show cases a jump that could not be done with jump repel before the change.
Fritz - NPC Character
Fritz is an NPC character. Fritz is a lightbug robot that leads the player throught the game and is the player's travel companion. Fritz was implemented as a spline following NPC that moves farther along the spline based on trigger volumes the player enters. Fritz can enter event triggers that cause him to do particular predetermined event behaviors at the next spline node.
I was responsible for building the Fritz System from the ground up. I was also responsible for the Fritz animation blueprint, the associated trigger volumes for Fritz, and the various Fritz event behaviors he had.
Fritz requires an array of splines in the order that Fritz will follow them. Draw numbers renders the number of each spline point in game. Fritz Travel Speed is the speed Fritz initially starts.
Location 1 is the trigger the player must pass through to increment Fritz's target location
Location 2 is the event trigger that Fritz will travel through to add an event to his event queue
Location 3 is the point on the spline where Fritz will run the event from 2
Three Fritz events were setup: wander, perch, and hover.
Level designers place target points into the world where they want Fritz to wander to during the event. The points are then made into a spline.
Note: Originally, Fritz would fly to each point at random but it did not look natural. I did not replace the target points with a spline to setup the event to prevent future builds from breaking. Fritz was a lower priority task for each department and splines may not have been able to made by level designers before the next milestone build. Creating splines from the current target points was safer.
Fritz perches at the target location. Designer's are given the choice for Fritz to look at the player or at a target point during the duration of the perch event.
Fritz hovers slowly around the spline point that the event was triggered on and looks at the player.
Other Fritz Features
When the player activates a new checkpoint, a reference of Fritz is found. Until Fritz makes it past that checkpoint, his current spline goal and index points are stored in the checkpoint.
On respawn, Fritz perches on the green orb on the checkpoint, leaving when the player leaves the checkpoint. Fritz's goal is set to what the last saved goal was by the checkpoint.
Speed up Behavior
When Fritz gets too far behind, he enables different speed up behaviors. Fritz is considered behind if he did not make it to his current objective before player tells Fritz to go to the next objective. Fritz will keep his behind status until he reaches his previous objective.
While behind, Fritz will no longer add new events. Depending on how many spline nodes behind Fritz is, Fritz will be given a speed up boost to catch up to the player.
Fritz Trigger Volumes
Fritz Trigger is triggered by the player and sets the new goal locations for Fritz taking in a spline goal and a spline node index on the spline.
1 in the image below is a "Will Trigger" check. If true, proceed and set "Will Trigger" to false.
2 is "Clear Fritz Events" and is set by level designers within the level editer. If set, Fritz will have any current events cleared and proceed to his next location.
The Fritz Event Trigger adds an event to Fritz's event queue. The Event Struct requires:
Enum of the event to be played
Duration of the event
An array of target points (for wander)
A bool indicating if the event lasts until stopped by a clear events trigger or if it is on a countdown
A bool telling the event that Fritz will look at the player or a target point (first target point in target points)
Fritz Event Trigger
Fritz Animation Blueprints
Fritz stores his current state in a Fritz State Struct. A copy of this struct is made in the animation blueprint and is used to determine which animation to play.
Fritz Core Loop
On event tick, Fritz determines how far behind he is, sets his speed if he's going to slow, and then does house keeping on events and behaviors.
Afterwards, if Fritz is currently in an event, he will branch out of the main loop and update events. Otherwise, he continues moving on the main path.
Set new distance on spline path, set location in the world, and set the new rotation.
Determine speed boost from being behind.
Determine if Fritz has caught up to his goal. If he has, allow for more events to be added.
Determine if Fritz is at the end of his spline. If he is, increment to the next spline in the spline path array and set current spline node index and distance on spline path to zero.