R18 is a vertical slice of an action/adventure solo game in a semi-open world based on platforming, alongside with fight and puzzles where the story takes an important place. This vertical is made on Unreal Engine with fifteen people working on it including three programmers.
When I joined Rescale Games, R 18 was already started. The project has known important changes since the beginning. At first all the game was about speed, I've made some gameplay objects like an accelerator and an online time attack. Then the game "opens" its worlds. We've spend one year to make a vertical slice with lots of changes. I was in charge of the core systems (quests, map, inventory, menu, interaction, manager) and UI of the game. With this role, I have touched a myriad of game's making likes Gameplay, UI, 3D modeling, physics and sound. This page represents a non-exhaustive list of my work at Rescale Games company.
As a semi-open world, the game needed a navigation system. So I've made an interactable map with basic fuctionalities like moving, zooming, and adding/removing marker. All the map icons can be found also on the in-game compass system. To manage easily the map icons, I created ,using Unreal Engine ECS (Entity Component System), a component named BPC_Icon. This component is reponsible of the map icon and compass icon of this owner. That means, the map system doesn't have to check if the object is either active, destroy or spawn. Only activated objects asks for an icon on map. Then in map system, I only used a list of UI icons to manage the movement, zoom and updating. I've also add some polish to the movement and zoom with some ease functions like SmoothStart2 and SmoothStart4.
Move, zoom and adding marker.
Icon Management after opening a chest.
The map system has different controls for the mouse/keyboard and gamepad. On the mouse/keyboard, the map cursor is completely free to move around and to move the map player has to drag the map. On the gamepad the map cursor is on center of the screen and the player moves directly the map. A near icon system ,that automatically snaps the world cursor to the nearest icon, is used to help player hover icons with gamepad.
At first the game had a survival aspect. Players had to manage their resources to be able to survive on this hostile planet. So I've had to make an inventory system. This inventory is really closed to resident-evil. Players had to manage object space in a grid container. Players are allowed to move ,use , equip, rotate and combine the item. The main problem was how to store the item in the inventory.. The inventory is fully 2D. It consists of a one dimension array containing items and a map that indicates the slots free. To manage the items easily, I’ve made a structure for the items containing its index, its size , image_angle,etc. I only store the top left index of the grid and calculate the rest when performing special operations (moving, rotating, combining, etc.). It has to be improved but now it does the job. For the next time, a 3D inventory would fit perfectly.
Moving, replacing and rotating objects.
Combining multiple elements and using them.
Then the second problem was how to store the item information. A combination creates a new object and it can be combined with others, etc. I chose to make something modular with a data asset and hash index. First, the data asset class of an item consists of some basic variables like an ID, a name, a base size (Vector2D describing the item shape in grid), if it is stackable, etc. All items are just a data asset of this class. Second, I’ve made a data asset to list all the possible recipes. Then to create a unique id, I use a polynomial rolling hash function. For a unique object, I calculate the id from its item name and for a combined object I use the combination of the two item names that create the new item with the hash function. It’s not perfect because two item names can have the same hash result with a probability of 1/1000000007. In the future, I’m going to use a stronger hash function like a SHA-256 or another one.
In addition to a navigation system, the game needed a quest system. Players can choose a secondary quest to follow, see the active quests and the completed ones. The quest system is quite simple. A quest is defined by its name, its unique id, its prerequisite quests and its tasks. When all of its tasks are completed, the quest is complete. A quest can have no tasks, it doesn't matter, the quest will be automatically completed. But how can we go from quest 1 to quest 2 ? I need to explain the event system beforehand.
Seeing, selecting and following quest.
Quest Data asset
Second, the event system is inherently linked to the quest system. It manages all the events of the game (update task, add quest, launch cinematic, active gameplay object, etc.). I used a mix of Mediator pattern and Observer pattern. I’ve made a mediator object that plays the role of the broadcaster and the managers (cinematic, inventory, etc.) act as subscribers who register and unsubscribe from the events of the mediator. Therefore, to get to quest 2, quest 1 has to have an “active quest” event to quest 2 when completed. Of course, we can define more dependencies with prerequisite quests, prerequisite tasks, etc. The system is wide, it’s just an overview. A lot of systems were involved, cinematic , UI, sound, enigma, etc. It was quite challenging and really fun to do.
So for the puzzles, the game needed an enigma system. The game has some interesting platforming puzzles. While the enigma objects are quite simple, we’ve got some interrupters, generators, chargers, moving objects, etc. But, how to manage many different behaviors and keep some unity between objects ? I started by using inheritance with a parent class. After making three objects with different behaviors, inheritance was a real pain to use.
Using Generator to open a locked door.
Other gameplay objects.
For that reason, I used an interface. It was really the thing to do. Every object can have its own implementation without carrying other useless pieces of code. When referencing an object to activate I'm only using the “actor” (base class for all world objects in unreal) reference for any objects and I can easily create another object without breaking everything. To supervise interaction between them, I use an enigma manager. It has a HashMap where key is the object activated and value is the instigator of the activation. I’m quite happy about this system. We used it a lot for various situations, puzzles, “cinematic” effects, etc.
For the last mechanic of this overview, I’m gonna talk about a mechanic that we need after many playtests during development: rewind time. To be honest, we just came up with the idea that a player can rewind only its position in a limited time. That simplifies a lot of things. Despite this simplification, it was harsh to do. The fight between accuracy and optimization was really intense . At first, I made a real simple recording system where each frame we stored a structure, composed by the player’s position and rotation . It was simple and it worked but it required a lot of resources due to the recording frequency. How to reduce recording and keep several levels of accuracy ?
A useful way to use rewind.
Rewind Debug for Spline creation.
A previous task ,that I made during the very first prototype, gave me a hint. I’ve made a ghost for a time attack mode. It's the same thing but here the player can control it. To create the ghost, I’ve used a spline that I create from the player's position and rotation. Thanks to this, I was able to recreate an approximative path from the previous player’s path. So with an editable record interval, I build a spline with a number of points defined by the time to rewind in seconds divided by the record interval. And then I make the player follow the spline trajectory until it reaches the end. It’s the “easy” mode but for our needs it’s great. Next time, I want to try to record the player’s input to easily use the player’s animation and simplify my code.
In this vertical slice, I learned a lot about many aspects of game development including Gameplay, System, UI and Sound. I also increased my knowledge in 3D Mathematics(Geometry, Coordinate Systems and Transformations, etc.). At the beginning, I wasn’t a big fan of the gameplay system and UI but due to games' needs I’ve got no choice to do those. In the end, I really fell in love with this kind of work. It was a great experience and a wonderful place to experiment things in a technical way. But I also got a better understanding of making games with a team : defining problems, searching together, discussing possible solutions, making a readable code and applying those. We solve a lot of things during development. We can be proud of ourselves to accomplish this huge vertical slice.