June was a super productive month on the locomotion side of things, expanding on and refining what I tackled in May. I also spent some time exploring procedural generation tactics & city building considerations.
Guided Platforming Continued
Last month I dug into this concept of guided platforming, i.e. a system to make traversing along platforming paths smooth and approachable by mapping out jump vectors & landing locations analytically. My first few iterations of this (back in 2020, and again last month) definitely achieved procedurally generating jump paths, but they fell short when it came to actual usability & fun. The main issue was that jump indications were very twitchy/inconsistent, which meant that players had to be extremely careful when planning a movement path, especially with multiple jumps involved, killing movement flow and leading to frustration.
To start this month off, I revisited how and where these jump paths and landing points were being generated and conveyed to the player. I wanted to see if I could use some kind of overlap system, where objects would have landing points configured as sphere-triggers, that, when overlapped by the player's larger overlap trigger, would show an indicator that tells the player, hey, you can jump here. The first thing I did was stress-test having a ton of sphere overlap components spawned in a 3D grid in the level, with the player character only evaluating nearby triggers.
While this was successful, having additional collision components for every possible landing position in the map felt risky long-term, and also felt incredibly clunky & time-consuming to set up. If only I could just do overlaps of the actual props in the map and evaluate them for landing positions! Well, actually, I could, thanks to mesh sockets.
Usually, mesh sockets are used as specific anchor points within the bounds/geometry of a mesh to attach something to said mesh. This is often employed via skeletal mesh sockets for stuff like holding weapons, attaching wearables like armor/helmets, stuff like that. However, mesh sockets are also available for static meshes, and since they essentially map out local-space transform points that can be referenced in various ways, they can also be used for plotting out acceptable landing positions on props.
Mesh sockets can be added to existing mesh assets manually in UE4/UE5 using the Static Mesh Editor or Python scripts, or they can be included in the mesh as part of the Unreal FBX import process. With these options available, I drafted up a rough pipeline for asset creation going forward that includes steps to place landing position sockets in props that are added into the game/into scenes, etc. Mesh sockets can even be accessed at a per-instance level for Instanced Static Meshes, which comes in super handy when thinking about procedural generation down the line, which will require ample use of ISMs. Proving all of this out was a necessary step, and one that went super smoothly.
In these examples, the player's platforming trigger sphere overlaps with instances of an air-conditioner mesh, which has mesh sockets applied. These overlaps are aggregated into a real-time list of candidate positions, which are then scored based on distance from the player and jump-direction alignment with the player's forward motion. If a winning position is found, it's highlighted by a ring UI element, and if the player is within jumping distance, the ring element fills up, telling the player that they can jump. This initial signaling of jump locations outside of actual jump range help a lot with communicating to the player where they can jump to.
Once I'd proven out that mesh sockets could be identified, aggregated, & scored, it was just a matter of actually plotting out the jump paths from the player's position to those landing points, and moving the player along them when jump is pressed. After a few attempts, I had a decent implementation, but it wasn't as accurate as I'd hoped, with some jumps not quite putting the player where they'd expect, undershooting or overshooting, etc. Luckily, I discovered that Unreal has a function that plots out a launch vector with configurable start & end locations, and controls for gravity & arc. Feeding this function the player start location and the highest scoring landing socket's end location worked beautifully, and I was now able to platform smoothly and consistently. There were some cases where the player would collide at the edge of the platform they were jumping towards, but with some simple edge-detection, I was able to also add a locomotion case for climbing up ledges. Platforming now feels smooth and accessible, as I'd hoped that it would.
Please excuse the excessive use of air conditioner props, this is just a test space.
I love the concept of being able to sneak into otherwise tough-to-access buildings through their vents, and so I set up a spline based system that allows me to author vent paths, with kit-pieces being placed & assigned platforming sockets. I also put together an "x-ray" effect when the player enters a vent that I think works well for occluding what's outside the vent, while still offering players a clear view of themselves/their movement direction.
A while back I picked up the Dragon IK plugin for Unreal, and until now I hadn't used it, but I tested it out on Snaccoon and found the results to be pretty solid for only having to spend like 20 minutes setting it up. This wasn't super critical to gameplay foundations that I've been focusing on, but for the low time-cost, it feels like a win to me.
Another consideration I had in service of making platforming/locomotion as smooth/accessible as possible was locking the player's movement direction when tight-roping along narrow surfaces like pipes or beams. I found that I was able to lock relative axis direction in Unreal's player movement component based on the direction of a given spline segment, which meant that I could set up spline paths by, again, evaluating sockets by a specific ID tag on appropriate props. I'm thinking I can ditch the spline component and just get the direction between the two closest points that the player is on, but for now this works pretty well and further highlights how abusing the socket system is pretty rad.
I have some lofty goals for the environments in Snaccoon, and so I'm going to be relying heavily on procedural tools for generating play spaces, for everything from room arrangements and decorations, to building designs & layouts, to city-block setups & roadways. I've done a ton of exploration into procedural generation tools, and pushing artistic intentionality & believable placement rules in procedural systems is a big passion of mine, and something that'll get put to the test extensively over the course of Snaccoon's development. In the second half of June, I spent some time trying out putting together a rough implementation of the Wave Function Collapse algorithm for creating buildings using tile-kits and an asset calibration tool that runs traces against kit piece variants and generates tile IDs stored to a data table for determining what pieces can be placed with neighboring pieces on each axis. I ran into some conceptual issues pretty quickly, and reached out on Twitter to see what other devs had to say regarding intentionality/physicality and WFC, and got a lot of great insight and feedback. I don't have anything to show just yet, but I have a much more clear plan of attack for July, and I'm excited to showcase more as things unfold.
That's all I have to share for June! Thank you again to everyone who's been reaching out/following the project, the excitement for Snaccoon is hugely motivating, and I'm very excited for what the future holds. 😊