A full recreation of Fortnite's building and editing system in Unreal Engine 5. Leverages C++ with GAS. Fully networked and server-authoritative.
This project recreates the classic grid-snapping building system for all of the 4 major structure types found in Fortnite: walls, ramps, floors, and pyramids. Each structure has unique placement logic (rules for where a building should be placed based on where the player is looking) and unique connection rules (rules for how one structure can connect to other structures).
When aiming to place a structure, the system displays a blue ghost preview of the structure at the targeted location. The ghost preview turns red if the placement is invalid, such as if its floating in the air.
Here is a side-by-side comparison of this project with Fortnite.
At the core of the build system is the Build gameplay ability. Upon activation, the gameplay ability spawns a targeting actor, which is standard practice in GAS for user previews and getting target data. The targeting actor uses a placement strategy to update its position based on factors like where the character is looking and the positions of nearby structures.
Each structure type has a different placement strategy, which allows for custom targeting behavior. For example, walls can be placed through other structures, such as ramps, while ramps cannot. These custom behaviors can be observed through playtesting in Fortnite.
When the player confirms the placement of a structure, it reports the targeted location back to the build ability. Since this information is on the server, the build ability sends the targeting information to the corresponding instance of the ability on the server. The server then validates the request by ensuring that the requested location follows all the placement rules for the structure type and the location is snapped to the grid.
In addition to building, this project also recreates Fortnite's famous structure editing mechanics. Players can reshape existing structures into similar structures, with different forms and properties. Each type of structure also has a unique method of editing. For example, walls use a 3x3 grid, ramps uses directions from dragging the mouse, floors uses a 2x2 grid, and pyramids uniquely has tile elevation when editing.
Edits also affect connection logic. For example, a ramp can connect to the top of a full-height wall, but not a half wall. As a consequence, editing a structure may disconnect it or its neighbors from nearby structures, causing them to collapse if not properly grounded.
Here is a side-by-side comparison showing this project with Fortnite, showcasing the editing system and structure collapse.
A somewhat less well-known Fortnite feature that this project also implements is the ability to edit your build previews. In other words, you can edit buildings before you even place them. After editing your build preview, all future builds of that structure type will use that edit until edited again. The editing behaves exactly the same as editing a placed structure.
Edited build previews use the connection rules for that specific edit type. This means that editing your build preview may make the structure unable to be placed in the same way as the full structure.
One main observation I made about Fortnite's build system is that it is fully tile-based. As such, edits are easily serializable as bitfields, where each bit corresponds to a tile being selected or unselected. These bitfields can then be used as keys to data assets to find relevant edit info efficiently. To make these bitfields easy to work with and designer-friendly, I created a custom property editor that allows inputting grid states visually, rather than just editing a raw integer.
Edit bitgrids are still efficiently represented as a single integer internally, but it now has an "array-like" front-end for easy editor usage. The behavior of the edit ability is driven largely by the contents of the data assets that use these edit bitgrids, making the system very data-driven.
Editing is implemented using an Edit gameplay ability paired with a custom targeting actor. The targeting actor is responsible for showing the edit tiles that the player interacts, displaying edit preview meshes, and interpreting input as changes to the edit grid.
Each structure has unique behavior with how they're edited. For example, walls cannot be rotated during editing, ramps use a dragging selection, and pyramid tiles change in height when selected. Each structure has a unique targeting actor to account for this, and the edit ability chooses the right one depending on the type of structure being edited. Each structure type has a unique targeting actor to handle all of the variation of each structure. However, they all inherit from a base targeting actor class to provide common functionality and to give the edit ability a shared interface to interact with.
When an edit is confirmed, the targeting actor's currently held edit is sent up to the server for validation and execution. The information is sent up to the server as custom target data, which includes edit bitfield and the structure's rotation along the Z-axis. This follows the same server-authoritative model as the Build ability.
The build preview case is a little more complicated, as it requires communication between the build ability and the edit ability. The build ability listens for the edit ability to start through gameplay tags, hiding its structure actor and removing input mapping to avoid interfering with the edit ability. The edit ability then spawns its targeting actor. In this case, when the edit is confirmed, the edit information goes to the build ability locally rather than the server.
Something that's equally important as placing structures is destroying them. In Fortnite, structures must connect to either ground or other structures to be valid. Free-floating structures are not allowed and get destroyed.
The approach I took is to consider connected structures as nodes in a graph. Whenever a structure is deleted, its neighbors are alerted, prompting each neighbor to check if its grounded or not. The ground check is done via breadth first search through the graph looking for ground. If it's not grounded (i.e. BFS exhausts the graph), it too is destroyed, further alerting its neighbors.
The most difficult part of all this was making it efficient enough to run seamlessly when destroying thousands of structures. Profiling, optimizations
Server authoritative, bandwidth optimizations, prediction