Player Housing
The housing system lets players purchase, decorate, and share personal houses. It supports grid-based furniture placement, visitor management, and persistent house layouts saved to the server. Housing is one of the most requested features in the monster capture genre.
Architecture Overview
| Class | File | Responsibility |
|---|---|---|
HousingService | Housing/HousingService.cs | House purchase, furniture CRUD, visitor management, save/load |
HouseData | Housing/HousingService.cs | Serializable house state (grid, furniture, ownership) |
FurniturePlacement | Core/OnlineTypes.cs | Per-furniture position and rotation on the grid |
Access via:
var housing = NakamaManager.Instance.Housing;
Housing is initialized automatically during connection when OnlineConfig.EnableHousing is true.
Configuration
| Config Field | Default | Description |
|---|---|---|
EnableHousing | true | Toggle the housing system |
MaxFurniturePerHouse | 50 | Maximum furniture items per house |
HouseGridSize | 16 x 16 | Grid dimensions in tiles |
AllowHouseVisitors | true | Default visitor access setting |
Purchasing a House
Players can purchase a house from a template:
HouseData house = await housing.PurchaseHouseAsync("template_small_cottage");
// house.Id -- unique house instance ID
// house.OwnerId -- the player's user ID
// house.TemplateId -- "template_small_cottage"
// house.GridWidth, house.GridHeight -- from config (16x16)
// house.Furniture -- empty list
// house.AllowVisitors -- from config default
House Ownership
bool hasHouse = housing.HasHouse;
HouseData myHouse = housing.MyHouse;
Furniture Placement
Furniture is placed on a grid with position and rotation.
Placing Furniture
bool placed = await housing.PlaceFurnitureAsync(
furnitureId: "sofa_red",
gridX: 5,
gridY: 3,
rotation: 0); // 0, 90, 180, 270
Placement fails if:
- The player does not own a house (
MyHouse == null). - The furniture count has reached
MaxFurniturePerHouse(default: 50).
Removing Furniture
bool removed = await housing.RemoveFurnitureAsync(
furnitureId: "sofa_red",
gridX: 5,
gridY: 3);
Removal matches on both furnitureId AND grid position, so multiple instances of the same furniture at different positions are handled correctly.
Furniture Data Model
[Serializable]
public class FurniturePlacement
{
public string FurnitureId; // References a furniture ScriptableObject
public int GridX; // Grid column
public int GridY; // Grid row
public int Rotation; // 0, 90, 180, or 270 degrees
public string CustomData; // Optional custom metadata
}
Furniture Events
housing.OnFurniturePlaced += (FurniturePlacement placement) =>
{
Debug.Log($"Placed {placement.FurnitureId} at ({placement.GridX}, {placement.GridY})");
};
housing.OnFurnitureRemoved += (string furnitureId) =>
{
Debug.Log($"Removed {furnitureId}");
};
Visitor Management
Toggling Visitor Access
// Allow visitors
await housing.SetVisitorsAllowedAsync(true);
// Set to private
await housing.SetVisitorsAllowedAsync(false);
The AllowVisitors flag on HouseData is updated immediately.
Visiting Another Player's House
HouseData theirHouse = await housing.VisitHouseAsync(ownerUserId);
bool isVisiting = housing.IsVisiting;
string visitingId = housing.VisitingHouseId;
// Leave when done
await housing.LeaveHouseAsync();
Visitor Events
housing.OnVisitorEntered += (string visitorUserId, string visitorName) =>
{
Debug.Log($"{visitorName} entered your house!");
};
housing.OnVisitorLeft += (string visitorUserId) =>
{
Debug.Log($"Visitor left.");
};
Saving and Loading
House state is persisted to the server:
// Save current house layout
await housing.SaveHouseAsync();
The OnHouseLoaded event fires when house data is loaded (either after purchase or when loaded from the server on connect):
housing.OnHouseLoaded += (HouseData house) =>
{
// Rebuild the house visual from house.Furniture list
foreach (var f in house.Furniture)
{
SpawnFurnitureVisual(f.FurnitureId, f.GridX, f.GridY, f.Rotation);
}
};
HouseData Model
The full HouseData class:
| Field | Type | Description |
|---|---|---|
Id | string | Unique house instance ID |
OwnerId | string | Owner's Nakama user ID |
OwnerName | string | Owner's display name |
TemplateId | string | House template reference |
GridWidth | int | Grid width in tiles |
GridHeight | int | Grid height in tiles |
Furniture | List<FurniturePlacement> | All placed furniture items |
AllowVisitors | bool | Whether visitors can enter |
CreatedAt | long | Creation timestamp (Unix ms) |
Housing as Social Space
Houses serve as social hubs where players can:
- Decorate and express -- place furniture from in-game shops or rewards.
- Invite friends -- share your house with the friends list.
- Host gatherings -- visitors can interact and chat inside the house.
- Showcase collections -- display trophies, rare items, or monster statues.
The visitor enter/exit events integrate with the social notification system so house owners are notified when players visit.