Pools, Fences, Stairs, Objects & Save System

Audience: Mid-level Unreal Engine 5 developers integrating BurbArchitect into their project.
Version: Reflects current source as of February 2026.

Table of Contents
  1. Pools
    1. How Pool Creation Works
    2. Pool Merging
    3. Water Volumes (UWaterComponent)
    4. Pool Materials
  2. Fences & Gates
    1. Fence Placement
    2. Fence Component (UFenceComponent)
    3. Gate Placement
    4. UFenceItem Data Asset
    5. UGateItem Data Asset
  3. Stairs
    1. Stair Placement
    2. AStairsBase — The Stair Actor
    3. StairsComponent
  4. Furniture & Objects (Buy Mode)
    1. Placement Modes
    2. ABuyObjectTool
    3. APlaceableObject
    4. UFurnitureItem Data Asset
    5. Catalog System
  5. Save / Load System
    1. Architecture Overview
    2. LotManager Save/Load Functions
    3. FSerializedLotData
    4. ULotSerializationSubsystem
    5. ULotDataAsset — Pre-Built Lots
    6. JSON Format
  6. Creating Custom Data Assets
    1. Creating a Custom Fence
    2. Creating a Custom Gate
    3. Creating a Custom Furniture Item
    4. Creating a Pre-Built Lot
    5. Catalog Categories & Subcategories
  7. Blueprint API Reference
    1. Pool System
    2. Fence & Gate System
    3. Stairs System
    4. Object Placement System
    5. Save/Load System
    6. Catalog System
  8. Quick Start Checklist

1. Pools

Pools in BurbArchitect are rooms built one level below the current floor. When viewing the ground floor (Level 1), the pool tool creates geometry at Level 0 — essentially a specialized basement room filled with a water volume.

1.1 How Pool Creation Works

ABuildPoolTool extends the room drawing tool (ABuildRoomTool). You draw a pool the same way you draw a room — click and drag a rectangular region on the grid. The tool automatically targets one level below the current traced level.

Workflow (runtime):

  1. Activate the pool tool (set your active ABuildTool to an instance of ABuildPoolTool).
  2. The player clicks and drags on the lot grid. The tool snaps to grid corners and shows wall previews at the target level.
  3. On release (BroadcastRelease), pool walls are committed at the sub-level and a water volume is generated.

1.2 Pool Merging

When a new pool is drawn adjacent to an existing pool, shared wall segments are automatically detected and removed. The PoolWallsToRemove array tracks edge IDs of walls that should be deleted, and PoolRoomsToMerge tracks room IDs whose water volumes need to be regenerated as a single merged volume.

The result is seamless, Sims-style pool merging — draw two adjacent rectangles and they become one L-shaped pool.

1.3 Water Volumes (UWaterComponent)

Each pool room gets a 3D water volume managed by UWaterComponent, a procedural mesh component. The water mesh consists of:

Water volumes are stored in the PoolWaterArray with O(1) lookup via PoolWaterMap (keyed by RoomID).

Key properties on ABuildPoolTool:

PropertyTypeDescription
DefaultWaterMaterialUMaterialInstance*Material applied to the water mesh. Assign your custom water shader here.
PoolFloorPatternUFloorPattern*Pattern used for pool bottom tiles.
PoolFloorMaterialUMaterialInstance*Material for the pool floor surface.
WaterSurfaceZOffsetfloatVertical offset of the water surface relative to ground level (default: -5.0). Negative values lower the surface below the surrounding ground.

Key UWaterComponent functions (all BlueprintCallable):

FunctionDescription
GeneratePoolWater(RoomID, BoundaryVertices, WaterSurfaceZ, PoolFloorZ, BaseMaterial)Creates a new water volume. Returns FPoolWaterData.
UpdatePoolWater(RoomID, BoundaryVertices)Updates an existing pool when its room polygon changes.
RemovePoolWater(RoomID)Destroys water mesh for the given room.
HasPoolWater(RoomID)Returns true if a water volume exists for this room.
DestroyAllWater()Removes every water volume on the lot.

1.4 Pool Materials

To customize the water appearance:

  1. Create a Material Instance based on your water material (translucent, depth fade, etc.).
  2. Assign it to DefaultWaterMaterial on your ABuildPoolTool instance.
  3. At runtime, the component creates a UMaterialInstanceDynamic per pool from your base material, stored in FPoolWaterData::WaterMaterial. You can modify per-pool parameters dynamically.

2. Fences & Gates

Fences are decorative only — they do not participate in room detection. They use static meshes (panels + posts) instead of procedural wall geometry.

2.1 Fence Placement

ABuildFenceTool extends ABuildHalfWallTool to inherit the drag/snap behavior along grid edges. During the drag phase, the tool spawns preview panel and post meshes. On release, actual FFenceSegmentData entries are committed to the UFenceComponent.

Runtime workflow:

  1. Set CurrentFenceItem on the tool to a UFenceItem data asset.
  2. Player clicks a grid corner and drags to define the fence line.
  3. Preview meshes appear along the path showing panels and posts.
  4. On release, the tool calls UFenceComponent::GenerateFenceSegment() to commit.

2.2 Fence Component (UFenceComponent)

The UFenceComponent is a scene component that manages all fence segments on a lot, parallel in architecture to the WallComponent for walls.

Each fence segment (FFenceSegmentData) stores:

Key functions (BlueprintCallable):

FunctionDescription
GenerateFenceSegment(Level, StartLoc, EndLoc, FenceItem)Creates a fence segment. Returns its index.
RemoveFenceSegment(FenceIndex)Destroys a segment and all its meshes.
FindFenceSegmentAtLocation(Location, Tolerance)Finds the nearest segment index. Returns -1 if none found.
AddGateToFence(FenceIndex, GateLocation, GateWidth, Gate)Inserts a gate, regenerating panels/posts around it.
RemoveGateFromFence(FenceIndex, Gate)Removes a gate and regenerates the fence.

2.3 Gate Placement

ABuildGateTool extends ABuildDoorTool but detects fences instead of walls. It uses FenceComponent->FindFenceSegmentAtLocation() to find the target fence, then spawns an AGateBase actor.

How gates integrate with fences:

  1. Gate tool hovers — DetectFenceSegment() checks if the cursor is over a fence.
  2. Position snaps along the fence segment via SnapToFence().
  3. Rotation auto-aligns to the fence direction via CalculateFenceRotation().
  4. On placement, AGateBase::OnGatePlaced() tells the FenceComponent to:
    • Force posts on each side of the gate opening.
    • Regenerate panels with a cutout for the gate.
  5. On deletion, AGateBase::OnDeleted_Implementation() regenerates the fence without the cutout.

AGateBase extends ADoorBase, so gates inherit the full door animation system (open/close skeletal mesh animations).

2.4 UFenceItem Data Asset

UFenceItem extends UArchitectureItem (which extends UCatalogItem). It defines:

PropertyTypeDescription
FencePanelMeshTSoftObjectPtr<UStaticMesh>The repeating panel mesh.
FencePostMeshTSoftObjectPtr<UStaticMesh>The post mesh (corners, ends, junctions).
PostSpacingint32Tiles between intermediate posts. 0 = no intermediate posts.
bPostsAtCornersboolForce posts at fence corners.
bPostsAtEndsboolForce posts at fence endpoints.
bPostsAtJunctionsboolForce posts at T-intersections / crosses.
FenceHeightfloatHeight in units (default 200).
PanelWidthfloatWidth of one panel mesh for spacing calculations.

Inherited from UCatalogItem:

PropertyTypeDescription
DisplayNameFTextName shown in catalog UI.
IconFSlateBrushThumbnail icon.
CostfloatIn-game price.
CategoryUCatalogCategory*Root catalog category.
SubcategoryUCatalogSubcategory*Optional subcategory.

2.5 UGateItem Data Asset

UGateItem extends UDoorItem (which extends UArchitectureItem). In addition to inherited portal properties (size, offset, snapping), it adds:

PropertyTypeDescription
GateSkeletalMeshTSoftObjectPtr<USkeletalMesh>Skeletal mesh for animation. Can reuse a door skeleton.
GateStaticMeshTSoftObjectPtr<UStaticMesh>Gate panel static mesh.
GateFrameMeshTSoftObjectPtr<UStaticMesh>Gate frame static mesh.

Inherited portal properties from UDoorItem: PortalSize, PortalOffset, HorizontalSnap, VerticalSnap, bSnapsToFloor, ClassToSpawn.


3. Stairs

Stairs connect two adjacent floor levels. BurbArchitect's stair system supports straight runs, 90° turns (left/right), and landings, all adjustable after placement via on-screen gizmo tools.

3.1 Stair Placement

ABuildStairsTool is the build tool. It creates a preview staircase that the player positions and rotates before committing.

Runtime workflow:

  1. Activate the stairs tool.
  2. The tool spawns a preview AStairsBase actor (DragCreateStairs).
  3. Player moves the cursor — the preview snaps to valid grid positions.
  4. RotateLeft / RotateRight rotate the preview by 90°.
  5. Clicking commits the stairs via CreateStairs().

Key ABuildStairsTool properties:

PropertyTypeDescription
StairsActorClassTSubclassOf<AStairsBase>Blueprint class to spawn. Override this for custom stair actors.
StairTreadMeshUStaticMesh*Mesh for individual stair treads.
StairLandingMeshUStaticMesh*Mesh for landing platforms.
DefaultStairsMaterialUMaterialInstance*Default material applied to stair meshes.
TreadsCountintNumber of treads to span one level (default: 12). At 25 units rise per tread, 12 treads = 300 units (one standard wall height).
HeightfloatTotal vertical travel (default: 300).
StairsThicknessfloatThickness of the stair underside (default: 15).
TreadSizeintDepth of each tread (default: 25).
LandingSizeintDepth of landing platforms (default: 95).

Mesh Socket Convention: Stair tread meshes must have Front_Socket and Back_Socket. The offset between them should be approximately (25, 0, 25) for standard rise. The tool chains treads via these sockets.

3.2 AStairsBase — The Stair Actor

AStairsBase is an abstract actor that encapsulates a complete staircase. It manages:

3.2.1 Stair Modules

Each staircase is defined as an array of FStairModuleStructure:

USTRUCT(BlueprintType)
struct FStairModuleStructure
{
    EStairModuleType StairType;    // Tread or Landing
    ETurningSocket TurningSocket;  // Idle, Right, or Left
};

A straight 12-tread staircase is 12 entries of {Tread, Idle}. To add a 90° turn, insert a {Landing, Right} or {Landing, Left} at the desired step.

The StepsPerSection property (default: 4) sets the minimum number of treads before a landing/turn can occur. Landings snap to multiples of this value.

3.2.2 Adjustment Gizmos

After placing stairs, clicking them enters Edit Mode with three gizmo handles:

GizmoTypeWhat It Does
AdjustmentTool_StartingStepStarting stepDrag to extend or shorten the bottom of the staircase.
AdjustmentTool_EndingStepEnding stepDrag to extend or shorten the top of the staircase.
AdjustmentTool_LandingToolLanding/turnDrag left or right to insert a 90° turn at that position.

Blueprint API for edit mode:

FunctionDescription
EnterEditMode()Shows gizmo handles.
ExitEditMode()Hides gizmo handles.
ToggleEditMode()Toggles.
RotateLeft() / RotateRight()Rotates the entire staircase 90°.
UpdateStairStructure(TurnSocket, LandingIndex)Programmatically insert a turn at a specific step.

3.2.3 Floor Cutaway

When stairs are committed (CommitStairs()), the system automatically cuts a hole in the upper floor where the staircase emerges. This uses CutAwayStairOpening(), which:

  1. Calculates the stair footprint at the top level via GetTopLevelFootprint().
  2. Removes floor/terrain tiles at those grid positions.
  3. Stores removed tiles in RemovedFloorTiles / RemovedTerrainTiles for undo support.

If stairs are deleted, RestoreStairOpening() puts those tiles back.

3.2.4 Validation

Before committing, ValidatePlacement() checks:

The bValidPlacement property and ValidationError string are updated for UI feedback.

3.3 StairsComponent

UStairsComponent is the procedural mesh component that generates the actual stair geometry. It manages an array of FStairsSegmentData entries. Most interaction goes through AStairsBase, but you can also use the component directly:

FunctionDescription
GenerateStairsMeshSection(InStairsData)Generates mesh for a single stair segment.
CommitStairsSection(InStairsData, TreadsMaterial, LandingsMaterial)Finalizes a segment with materials.
DestroyStairsSection(InStairsData)Removes a specific section.
FindExistingStairsSection(TileCornerStart, Structures, OutStairs)Checks if stairs already exist at a location.

4. Furniture & Objects (Buy Mode)

The object placement system handles furniture, decorations, and fixtures. It supports four placement modes: Floor, Wall Hanging, Ceiling Fixture, and Surface.

4.1 Placement Modes

UENUM(BlueprintType)
enum class EObjectPlacementMode : uint8
{
    Floor,           // Chairs, tables — snaps to floor grid
    WallHanging,     // Posters, shelves — snaps to wall surfaces
    CeilingFixture,  // Chandeliers — snaps to ceiling
    Surface          // (Future) — on countertops, desks
};

4.2 ABuyObjectTool

ABuyObjectTool is the build tool for placing objects. It reads placement rules from the CurrentCatalogItem (UFurnitureItem*) and delegates to the appropriate handler.

Key properties:

PropertyTypeDescription
CurrentCatalogItemUFurnitureItem*The furniture item being placed. Set this before activating the tool.
bValidPlacementbool (read-only)Whether the current position is a valid placement. Use for visual feedback (green vs red ghost).
CurrentPlacementModeEObjectPlacementMode (read-only)Derived from the catalog item's PlacementRules.

Placement helpers (all BlueprintCallable):

FunctionDescription
TraceForWall(FromLocation, OutHit)Raycasts for a wall mesh. Returns true if hit.
CalculateWallMountPosition(WallHit, HeightAboveFloor, WallOffset, Level)Calculates world position on a wall surface.
CalculateWallMountRotation(WallNormal)Calculates rotation facing away from wall.
CheckAdjacentWalls(Row, Col, Level, OutWallNormal)O(1) grid check for adjacent walls.
GetAdjacentWallNormals(Row, Col, Level)Returns all wall normals adjacent to a tile.
CalculateCeilingHeight(Level)Returns world Z of the ceiling at a level.
CheckCeilingExists(Row, Col, Level)Returns true if a ceiling (roof or upper floor) exists.

4.3 APlaceableObject

APlaceableObject is the base class for all placed furniture/decor actors. It's replicated for multiplayer and stores placement metadata for serialization.

Properties:

PropertyTypeDescription
CurrentFloorint32Floor level this object is on. Replicated + SaveGame.
PlacementModeEObjectPlacementModeHow this object was placed. Replicated + SaveGame.
PlacedRow / PlacedColumnint32Grid coordinates for floor/ceiling objects. Replicated + SaveGame.
WallNormalFVectorFor wall-mounted objects, the wall's outward normal. Replicated + SaveGame.

All your custom furniture Blueprints should extend APlaceableObject (or a Blueprint subclass of it).

4.4 UFurnitureItem Data Asset

UFurnitureItem extends UCatalogItem and adds:

PropertyTypeDescription
ClassToSpawnTSoftClassPtr<APlaceableObject>The Blueprint class spawned when this item is placed.
PlacementRulesFPlacementConstraintsDefines how and where this item can be placed.

FPlacementConstraints

The constraints struct is the core of the placement validation system:

General:

PropertyDefaultDescription
PlacementModeFloorDetermines snap behavior — Floor, WallHanging, CeilingFixture, or Surface.
bCanPlaceOutdoorstrueWhether the object can be placed outside of enclosed rooms.
GridSize(1, 1, 1)Footprint in tiles (X × Y × Z).

Floor placement:

PropertyDefaultDescription
bMustBeAgainstWallfalseRequires an adjacent wall (toilets, beds against walls).
bAutoRotateFromWalltrueAuto-faces away from the wall when placed against one.
bRequiresFloortrueMust have a floor tile underneath.

Wall hanging:

PropertyDefaultDescription
WallMountHeight150.0Height above floor in cm.
bCanRotateOnWalltrueAllow 360° rotation on the wall surface.
WallOffset5.0Distance from wall surface in cm.

Ceiling fixture:

PropertyDefaultDescription
CeilingOffset20.0Distance from ceiling surface in cm.

Tip: The Editor uses EditCondition and EditConditionHides metadata so only relevant properties show in the Details panel based on the selected PlacementMode.

4.5 Catalog System

All catalog items (furniture, fences, gates, architecture) are auto-discovered by the UCatalogSubsystem at game startup. It scans the Asset Registry for all UCatalogItem subclass assets — regardless of directory — making it mod-friendly.

Getting items in Blueprint:

// Get the subsystem
UCatalogSubsystem* Catalog = GetGameInstance()->GetSubsystem<UCatalogSubsystem>();

// Browse categories
TArray<UCatalogCategory*> Categories = Catalog->GetRootCategories();

// Get items in a category (loads on demand)
TArray<UCatalogItem*> Items = Catalog->GetItemsInCategory(MyCategory);

// Search by name
TArray<UCatalogItem*> Results = Catalog->SearchItemsByName("Chair");

The catalog uses lazy loading — items are stored as FSoftObjectPath and only loaded when requested. For UI lists that just need counts/names, use GetItemPathsInCategory() / SearchItemPathsByName().


5. Save / Load System

BurbArchitect provides a complete serialization pipeline with multiple output formats.

5.1 Architecture Overview

LotManager (high-level API - BlueprintCallable) └─ ULotSerializationSubsystem (GameInstance subsystem - does the work) ├─ SerializeLot() → FSerializedLotData ├─ DeserializeLot() ← FSerializedLotData ├─ ExportToJSON() → .json file └─ ImportFromJSON() ← .json file ULotSaveGame (USaveGame) (binary .sav files in Saved/SaveGames/) ULotDataAsset (UDataAsset) (packaged assets for default/shipped lots)

5.2 LotManager Save/Load Functions

All of these are BlueprintCallable and available on any ALotManager reference:

FunctionDescription
SaveLotToSlot(SlotName)Saves to Unreal's binary SaveGame system. Files land in Saved/SaveGames/<SlotName>.sav. Returns true on success.
LoadLotFromSlot(SlotName)Loads from a save slot. Clears the current lot first, then rebuilds everything. Returns true on success.
ExportLotToFile(FilePath)Exports to a human-readable JSON file at the given absolute path. Great for sharing lots or debugging.
ImportLotFromFile(FilePath)Imports a lot from a JSON file.
LoadDefaultLot(LotAsset)Loads a pre-built lot from a ULotDataAsset. Use for starter homes, pre-furnished lots, etc.
SaveAsDataAsset(AssetName, PackagePath)Editor only. Creates a ULotDataAsset in your Content Browser that can be packaged with the game.

5.3 FSerializedLotData

This is the master struct containing everything needed to reconstruct a lot:

FieldTypeWhat It Stores
GridConfigFLotGridConfigGrid dimensions, tile size, floor/basement count, current level.
WallNodesTArray<FSerializedWallNode>Wall graph vertices (node ID, row, col, level).
WallEdgesTArray<FSerializedWallEdge>Wall segments connecting nodes (edge ID, rooms, height, pattern/material paths).
FloorTilesTArray<FSerializedFloorTile>Individual floor tiles (row, col, level, pattern/material, active sections bitmask).
RoofsTArray<FSerializedRoofData>Roof structures (class, location, dimensions, pitch, material).
StairsTArray<FSerializedStairsData>Staircases (class, location, direction, modules, meshes).
TerrainFSerializedTerrainDataTerrain tiles with corner heights.
PortalsTArray<FSerializedPortalData>Doors and windows (class, location, rotation, attached wall edge).
PlacedObjectsTArray<FSerializedPlacedObject>Furniture/decor (class path, transform, level).
PoolWaterTArray<FSerializedPoolWater>Pool water volumes (room ID, boundary vertices, surface/floor Z, material).
FencesTArray<FSerializedFenceSegment>Fence segments (start/end locations, level, fence item asset path).
TileRoomIDsTArray<int32>Flattened room ID grid: [Level * GridSizeX * GridSizeY + Row * GridSizeX + Col].
UpperFloorTilesTArray<int32>Packed tile references: (Level << 24) | (Row << 12) | Column.
LotNameFStringUser-friendly lot name.
DescriptionFStringOptional description.
SaveTimestampFDateTimeWhen the lot was saved.

5.4 ULotSerializationSubsystem

This UGameInstanceSubsystem handles all the actual serialization work. Access it from any Blueprint or C++:

ULotSerializationSubsystem* Serializer = GetGameInstance()->GetSubsystem<ULotSerializationSubsystem>();

// Serialize the entire lot
FSerializedLotData Data = Serializer->SerializeLot(LotManager);

// Validate data
bool bValid = Serializer->ValidateLotData(Data);

// Export to JSON
Serializer->ExportToJSON(Data, TEXT("C:/MyLots/TestHouse.json"));

// Import from JSON
FSerializedLotData ImportedData;
Serializer->ImportFromJSON(TEXT("C:/MyLots/TestHouse.json"), ImportedData);

// Apply to a lot
Serializer->DeserializeLot(LotManager, ImportedData);

The subsystem serializes each component independently:

Serialize FunctionDeserialize FunctionWhat
SerializeWallGraph()DeserializeWallGraph()Wall nodes + edges
SerializeFloorComponent()DeserializeFloorComponent()Floor tiles
SerializeRoofComponent()DeserializeRoofComponent()Roof actors
SerializeStairsComponent()DeserializeStairsComponent()Staircase actors
SerializeTerrainComponent()DeserializeTerrainComponent()Terrain heightmap
SerializeWaterComponent()DeserializeWaterComponent()Pool water volumes
SerializeFenceComponent()DeserializeFenceComponent()Fence segments
SerializePortals()DeserializePortals()Doors + windows
SerializePlacedObjects()DeserializePlacedObjects()Furniture/decor
SerializeRoomIDs()DeserializeRoomIDs()Room assignment grid

5.5 ULotDataAsset — Pre-Built Lots

ULotDataAsset is a UDataAsset containing an FSerializedLotData. Use it for default/starter lots shipped with your game.

Properties:

PropertyTypeDescription
LotDataFSerializedLotDataThe complete serialized lot.
ThumbnailUTexture2D*Preview image for menus.
CategoryFStringOrganizational category (e.g., "Starter", "Large").
TagsTArray<FString>Filter tags (e.g., "Modern", "Colonial").
Priceint32Cost to place this lot (0 = free).

Functions:

FunctionDescription
ValidateLotData()Returns true if the stored data is valid.
GetLotName()Returns LotData.LotName if set, otherwise the asset name.
GetDescription()Returns LotData.Description.

5.6 JSON Format

The JSON export uses Unreal's FJsonObjectConverter to serialize FSerializedLotData. The resulting file is human-readable and diff-friendly, making it ideal for:


6. Creating Custom Data Assets

6.1 Creating a Custom Fence

  1. Prepare meshes:
    • Create a panel mesh — one repeating fence section. The mesh width should match your intended PanelWidth value.
    • Create a post mesh — the vertical element placed at corners, ends, and intermediate points.
  2. Create the data asset:
    • In the Content Browser, right-click → Miscellaneous → Data Asset.
    • Select FenceItem as the class.
    • Name it descriptively (e.g., FI_WoodPicket).
  3. Configure properties:
    • Set FencePanelMesh and FencePostMesh to your static meshes.
    • Set PanelWidth to match your mesh (e.g., 100.0 for a 1-tile-wide panel).
    • Set FenceHeight (default 200).
    • Configure PostSpacing1 means a post every tile, 2 every other tile, etc.
    • Enable bPostsAtCorners, bPostsAtEnds, bPostsAtJunctions as needed.
  4. Set catalog properties:
    • Set DisplayName, Icon, and Cost.
    • Assign a Category (create a UCatalogCategory data asset if you don't have one).
    • Optionally assign a Subcategory.
  5. Done! The CatalogSubsystem will auto-discover your asset on next game launch. Assign it to ABuildFenceTool::CurrentFenceItem to use it.

6.2 Creating a Custom Gate

  1. Prepare meshes:
    • Create gate panel, frame, and optionally skeletal meshes.
    • Gates reuse the door animation skeleton — your skeletal mesh should have the same bone structure as doors if you want open/close animations.
  2. Create the data asset:
    • Right-click → Miscellaneous → Data Asset → GateItem (e.g., GI_IronGate).
  3. Configure:
    • Set GateSkeletalMesh, GateStaticMesh, GateFrameMesh.
    • Set PortalSize (width × height of the gate opening).
    • Set HorizontalSnap for placement snapping along the fence.
    • Set ClassToSpawn to your gate Blueprint class (must extend AGateBase or its Blueprint equivalent).
    • Set catalog properties (DisplayName, Icon, Cost, Category).

6.3 Creating a Custom Furniture Item

  1. Create the actor Blueprint:
    • Create a new Blueprint extending APlaceableObject (or a child class).
    • Add your static/skeletal mesh components, collision, interaction logic, etc.
  2. Create the data asset:
    • Right-click → Miscellaneous → Data Asset → FurnitureItem (e.g., FI_DiningChair).
  3. Configure:
    • Set ClassToSpawn to your Blueprint class.
    • Configure PlacementRules:
      • Floor item (chair, table): PlacementMode = Floor, set GridSize, bRequiresFloor = true.
      • Wall item (painting, shelf): PlacementMode = WallHanging, set WallMountHeight, WallOffset.
      • Against-wall item (toilet, bed): PlacementMode = Floor, bMustBeAgainstWall = true, bAutoRotateFromWall = true.
      • Ceiling item (chandelier): PlacementMode = CeilingFixture, set CeilingOffset.
    • Set catalog properties (DisplayName, Icon, Cost, Category).
  4. Test:
    • Launch PIE, open buy mode, find your item in the catalog.
    • Verify placement rules (snapping, validation, rotation).

6.4 Creating a Pre-Built Lot

  1. Build the lot in-game using the build tools (walls, floors, roofs, furniture, etc.).
  2. Export as data asset (Editor only):
    • In the LotManager Details panel, use SaveAsDataAsset("DA_StarterHome", "/Game/DefaultLots/").
    • This creates a ULotDataAsset in your Content Browser.
  3. Or export as JSON:
    • Call LotManager->ExportLotToFile("C:/MyLots/StarterHome.json").
    • Import later with ImportLotFromFile().
  4. Customize the asset:
    • Set Thumbnail, Category, Tags, and Price on the data asset.
  5. Load at runtime:
    // In Blueprint or C++
    ULotDataAsset* StarterHome = LoadObject<ULotDataAsset>(nullptr, TEXT("/Game/DefaultLots/DA_StarterHome"));
    LotManager->LoadDefaultLot(StarterHome);

6.5 Catalog Categories & Subcategories

To organize items in your catalog UI:

  1. Create a category: Right-click → Data Asset → CatalogCategory (e.g., CC_Seating).
    • Set DisplayName, Icon, SortOrder (lower numbers appear first).
  2. Create subcategories (optional): Right-click → Data Asset → CatalogSubcategory.
    • Set DisplayName, SortOrder.
  3. Assign to items: On each UCatalogItem, set Category and optionally Subcategory.
  4. The CatalogSubsystem auto-discovers and organizes everything.

7. Blueprint API Reference

7.1 Pool System

ABuildPoolTool (extends ABuildRoomTool):

NodeDescription
DefaultWaterMaterialSet the water material for new pools.
PoolFloorPattern / PoolFloorMaterialSet the pool bottom appearance.
WaterSurfaceZOffsetAdjust how far below ground the water surface sits.

UWaterComponent (on LotManager):

NodeDescription
Generate Pool WaterCreate a water volume for a room.
Update Pool WaterUpdate when room shape changes.
Remove Pool WaterDelete a pool's water.
Has Pool WaterCheck if a room has water.
Destroy All WaterNuclear option — removes all water.

7.2 Fence & Gate System

ABuildFenceTool:

NodeDescription
Current Fence ItemSet before placement to define which fence to build.

UFenceComponent (on LotManager):

NodeDescription
Generate Fence SegmentCreate a fence between two points. Returns index.
Remove Fence SegmentDelete a fence by index.
Find Fence Segment At LocationLook up a fence near a world position.
Add Gate To FencePlace a gate on a fence (regenerates panels).
Remove Gate From FenceRemove a gate (regenerates panels).

AGateBase:

NodeDescription
On Gate PlacedCall after spawning to integrate with fence.

7.3 Stairs System

ABuildStairsTool:

NodeDescription
Create Stairs PreviewSpawn the ghost staircase for placement.
Create StairsCommit the preview stairs to the lot.
Stairs Actor ClassSet to your custom stairs Blueprint class.

AStairsBase:

NodeDescription
Initialize StairsSet up with location, direction, modules, meshes.
Generate Stairs MeshBuild the procedural mesh.
Update Stairs MeshRebuild after configuration changes.
Commit StairsFinalize placement and cut floor opening.
Destroy StairsRemove the staircase entirely.
Enter Edit Mode / Exit Edit ModeShow/hide adjustment gizmos.
Rotate Left / Rotate Right90° rotation.
Validate PlacementCheck if current position is valid.
Cut Away Stair OpeningManually cut the upper floor.
Restore Stair OpeningUndo the floor cut (for deletion).
Get Bottom Landing Tile / Get Top Landing TileGrid positions for validation.
Get Bottom Level Footprint / Get Top Level FootprintAll tiles occupied by the staircase.

7.4 Object Placement System

ABuyObjectTool:

NodeDescription
Current Catalog ItemSet the UFurnitureItem to place.
bValid PlacementRead to check if current position is valid.
Trace For WallRaycast for wall surfaces.
Calculate Wall Mount PositionGet world position on a wall.
Calculate Wall Mount RotationGet rotation facing away from wall.
Check Adjacent WallsCheck if tile has a wall next to it.
Get Adjacent Wall NormalsGet all wall normals near a tile.
Calculate Ceiling HeightGet ceiling Z for a level.
Check Ceiling ExistsVerify ceiling at a tile.

7.5 Save/Load System

ALotManager:

NodeDescription
Save Lot To SlotSave to binary .sav file.
Load Lot From SlotLoad from binary .sav file.
Export Lot To FileExport to JSON.
Import Lot From FileImport from JSON.
Load Default LotLoad a ULotDataAsset.

ULotSerializationSubsystem (GameInstance subsystem):

NodeDescription
Serialize LotConvert a lot to FSerializedLotData.
Deserialize LotApply FSerializedLotData to a lot.
Validate Lot DataCheck data integrity.
Export To JSONWrite serialized data to a JSON file.
Import From JSONRead serialized data from a JSON file.

7.6 Catalog System

UCatalogSubsystem (GameInstance subsystem):

NodeDescription
Get Root CategoriesAll top-level categories (sorted).
Get SubcategoriesSubcategories under a category.
Get Items In CategoryAll items in a category (loads on demand).
Get Items In SubcategoryItems in a specific subcategory.
Get Item Paths In CategoryFast — returns paths without loading.
Search Items By NameCase-insensitive partial match.
Load Item / Load ItemsLoad catalog items on demand from paths.
Refresh CatalogRescan Asset Registry (useful in editor).

Quick Start Checklist

This document covers BurbArchitect's pool, fence, stair, object, and save systems. For walls, floors, roofs, and terrain, see the companion user guides.