Skip to content
smartargs
VantageDocumentation

Building reference

The builder and its input, preview and construction components, the buildable and placement rule assets, and the API for writing your own placement rules. For how to use it, see Building.

VtUnitBuilder

Component. Add it with Add Component → Vantage → Building → VtUnitBuilder.

Placement mode for a player. Spawns a ghost that follows the cursor, snaps it per the buildable’s snap mode, lets the player rotate it, validates every frame, and on TryPlace pays the cost and spawns the prefab. TryDemolish removes a placed piece and refunds its cost. Costs are paid from CostSource: the unit’s own bag and wallet, or the VtSharedStash that serves it.

Scripting API

Member Description
bool IsPlacing { get; } True between BeginPlacement and TryPlace or CancelPlacement.
VtBuildableDefinition CurrentBuildable { get; } The buildable being placed, or null.
GameObject CurrentGhost { get; } The ghost preview, or null.
Vector3 CurrentPosition { get; } Ghost world position this frame.
Quaternion CurrentRotation { get; } Ghost world rotation this frame.
float CurrentYaw { get; } Rotation the player chose, in degrees around the up axis.
bool CurrentValidationPasses { get; } Whether the ghost transform passes validation.
VtBuildFailureReason CurrentValidationReason { get; } Why validation fails, VtBuildFailureReason.None when it passes.
VtBuildRefusal CurrentRefusal { get; } Why validation fails, with the refusing rule’s key; VtBuildRefusal.None when it passes.
VtBuildRefusal LastRefusal { get; } The most recent refusal of a builder call, with the refusing rule’s key.
bool IsPlacementHeld { get; } True while HoldPlacement keeps the ghost where it is instead of following the cursor.
IVtCostSource CostSource { get; } Where building costs are paid from and refunds go to: the source set with SetCostSource, else the VtSharedStash that serves this unit, else its own bag and wallet. Tools in Required Items are always checked in the unit’s own bag.
event Action<VtBuildableDefinition, GameObject> OnPlacementStarted Fires when BeginPlacement succeeds, with the ghost.
event Action<VtBuildableDefinition, Vector3, Quaternion, VtBuildRefusal> OnPlacementMoved Fires every frame while placing: (buildable, position, rotation, refusal). The placement is valid when VtBuildRefusal.IsNone. Drive ghost tint from it.
event Action<VtBuildableDefinition, GameObject> OnPlaced Fires after a successful TryPlace with the spawned instance.
event Action<VtBuildableDefinition> OnPlacementCancelled Fires when CancelPlacement ends a placement.
event Action<VtBuildableDefinition, VtBuildRefusal> OnBuildFailed Fires when a builder call is refused, with the refusal.
event Action<VtBuildableDefinition, VtUnit> OnDemolished Fires after a successful TryDemolish, before the instance is destroyed.
void Initialize() Find the sibling inventory, wallet, level and quest log the builder uses. Safe to call more than once.
void SetCursorProvider(IVtBuildCursorProvider provider) Replace the cursor source, such as a gamepad, touch, VR or a fixed point. Null restores the screen cursor.
void SetCostSource(IVtCostSource source) Pay for buildings from source, such as a pool of your own. Null goes back to the default choice described on CostSource.
bool IsAvailable(VtBuildableDefinition buildable, out VtBuildFailureReason reason) Every check that does not depend on a position: unlock, required items, level, quests, item and currency cost.
bool BeginPlacement(VtBuildableDefinition buildable, out VtBuildFailureReason reason) Enter placement mode: spawn the ghost and start following the cursor. The ghost’s colliders, NavMesh obstacles, sockets and placement markers are off, so it never blocks its own placement, carves the NavMesh or catches clicks.
bool BeginPlacement(VtBuildableDefinition buildable, float yaw, out VtBuildFailureReason reason) Enter placement mode with the ghost already turned to yaw degrees, such as the rotation of the piece placed before it. A buildable that cannot rotate starts at 0.
void Rotate(int steps) Rotate the ghost by steps times the buildable’s rotation step. Negative turns the other way.
void RotateClockwise() One rotation step clockwise.
void RotateCounterClockwise() One rotation step counter-clockwise.
void HoldPlacement() Keep the ghost at its current position and rotation instead of following the cursor, such as while the builder walks there to place it. It is still checked every frame. Ends with ReleasePlacement or when placing ends. Rotating does nothing while held.
void ReleasePlacement() Let the ghost follow the cursor again after HoldPlacement.
void RefreshPlacement() Move the ghost to the cursor, or keep it where it is while held, and check it now instead of on the next frame. Fires OnPlacementMoved. Does nothing while not placing.
void CancelPlacement() Leave placement mode without placing. Nothing was paid, so nothing is refunded.
bool TryPlace(out VtBuildFailureReason reason) Place at the current ghost transform. Authority-gated. Re-validates, then pays the cost, spawns the prefab with a VtPlacedBuildable marker, attaches a VtBuildSite when the buildable has a build time, and ends placement.
bool TryPlaceAt(VtBuildableDefinition buildable, Vector3 position, Quaternion rotation, out VtBuildFailureReason reason) Place buildable at an explicit pose, running the same availability, cliff, overlap and placement-rule checks as TryPlace. This is what the authority calls for a placement a client requested. Does not touch the ghost.
bool TryDemolish(VtUnit target, out VtBuildFailureReason reason) Remove a placed piece and refund its cost, to the shared stash that paid for it when there was one, else to CostSource. An unfinished site refunds everything when the buildable has Refund On Cancel; a finished piece refunds Demolish Refund Fraction. Authority-gated. Refuses with VtBuildFailureReason.NotABuildable for anything this system did not place.

VtBuildInput

Component. Add it with Add Component → Vantage → Building → VtBuildInput. Adds VtUnitBuilder automatically.

The player’s controls for VtUnitBuilder. While a building is being placed, Confirm Target (left-click, gamepad South) places it, Cancel (Esc, gamepad East) or Command (right-click) stops placing, Rotate Placement (R, d-pad right) and Rotate Placement Back (Shift + R, d-pad left) turn it, and the scroll wheel turns it instead of zooming the camera. Placing is started by a VtHotbar, a build menu or VtUnitBuilder.BeginPlacement.

Inspector fields

Field Type Default Description
Confirm Action (confirmAction) InputActionReference None Places the building. Empty uses Confirm Target, the left mouse button and gamepad South by default. When it shares a button with Command, placing wins.
Cancel Action (cancelAction) InputActionReference None Stops placing. Empty uses Cancel, Esc and gamepad East by default.
Command Action (commandAction) InputActionReference None Also stops placing. Empty uses Command, the right mouse button by default.
Rotate Action (rotateAction) InputActionReference None Turns the building one step clockwise. Empty uses Rotate Placement, R and d-pad right by default.
Rotate Back Action (rotateBackAction) InputActionReference None Turns the building one step counter-clockwise. Empty uses Rotate Placement Back, Shift + R and d-pad left by default.
Rotate With Scroll Wheel (rotateWithScrollWheel) bool On The scroll wheel turns the building while placing, and the camera does not zoom.
Keep Placing (keepPlacing) VtKeepPlacing WhileModifierHeld Whether the same building is picked up again after one is placed.
Keep Placing Modifier Action (keepPlacingModifierAction) InputActionReference None Held to keep placing when Keep Placing is While Modifier Held. Empty uses Additive Modifier, Shift by default.
Out Of Reach (outOfReach) VtOutOfReachPlacement Refuse What placing beyond the piece’s range does. Walk There holds the ghost, walks the player into range and places it on arrival; it needs a VtTopDownClickToMove on the player.

Scripting API

Member Description
VtKeepPlacing KeepPlacing { get; set; } Whether the same building is picked up again after one is placed.
VtOutOfReachPlacement OutOfReach { get; set; } What placing beyond the piece’s range does.
bool IsWalkingToPlace { get; } True while the player walks to a held ghost to place it there.
bool RotateWithScrollWheel { get; set; } Whether the scroll wheel turns the building while placing instead of zooming the camera.
VtUnitBuilder Builder { get; } The builder this reads input for.
bool BlocksPointerThisFrame { get; } True while placing and on the frame placing ended. Click input and selection ignore pointer presses then, so a placing or cancelling click does not also walk or select.
void Initialize() Find the builder and the VtAbilityHotkeys next to it and listen to them. Idempotent; public for components added at runtime.
VtBuildFailureReason Confirm() Place the building at the ghost, then pick it up again when KeepPlacing says so. Returns why the builder refused, VtBuildFailureReason.AuthorityNotLocal when the placement was sent to the authority, or VtBuildFailureReason.NotPlacing when nothing is being placed. With OutOfReach set to VtOutOfReachPlacement.WalkThere, a ghost beyond the range is held and the player walks there; that returns VtBuildFailureReason.OutOfRange and IsWalkingToPlace turns true. Confirming again while walking aims at the cursor anew.
void Cancel() Stop placing without placing anything.

VtBuildGhostStyle

Component. Add it with Add Component → Vantage → Building → VtBuildGhostStyle. Adds VtUnitBuilder automatically.

Colours the placement ghost by whether the piece can go there: validColor while VtUnitBuilder.CurrentRefusal is none, refusedColor otherwise. The colour changes only when the answer changes. Mesh and skinned mesh renderers are coloured; particles and lines keep their look. Put it on the player next to the builder. For the reason as text, read VtBuildState.PlacementRefusalText from a VtBuildPresenter.

Inspector fields

Field Type Default Description
Look (look) VtBuildGhostLook Auto Auto tints a buildable’s own ghost prefab and replaces the materials of a ghost copied from the real prefab.
Valid Color (validColor) Color #73E69980 Ghost colour where the piece can be placed.
Refused Color (refusedColor) Color #F7525280 Ghost colour where it cannot.
Valid Material (validMaterial) Material None Material for a valid ghost when materials are replaced. Empty uses a see-through material in the valid colour.
Refused Material (refusedMaterial) Material None Material for a refused ghost when materials are replaced. Empty uses a see-through material in the refused colour.

Scripting API

Member Description
VtBuildGhostLook ActiveLook { get; } The look used for the ghost being placed now, with VtBuildGhostLook.Auto resolved.
bool ShowsValid { get; } Whether the ghost shows the valid colour. False while nothing is placed.
void Initialize() Find the builder and listen to it. Colours a ghost that is already out. Idempotent; public for components added at runtime.

VtBuildGridPatch

Component. Add it with Add Component → Vantage → Building → VtBuildGridPatch. Adds VtUnitBuilder automatically.

Shows the building grid around the ghost while a Grid or Socket piece is being placed: a small patch of cells that lies on the ground and fades out at its edge. Cells the piece cannot use are drawn in refusedColor: cells the VtCliffMap marks blocked, ramps, and cells holding a collider on the piece’s Forbidden Overlap Mask, so the player sees why a spot is refused before clicking. Put it on the player next to the builder.

Inspector fields

Field Type Default Range Description
Radius Cells (radiusCells) int 3 ≥ 1 Cells shown on each side of the ghost’s cell. The outer cells fade out.
Cell Gap (cellGap) float 0.06 0 to 0.45 Gap between cells as a share of the cell size; the ground shows through it as grid lines.
Open Color (openColor) Color #FFFFFF29 Colour of cells a piece can stand on.
Refused Color (refusedColor) Color #F7525259 Colour of cells it cannot.
Refresh Seconds (refreshSeconds) float 0.25 ≥ 0.05 Seconds between checks of the cells for colliders while the ghost stands still.
Height Offset (heightOffset) float 0.03 ≥ 0 Height of the patch above the ground.
Material (material) Material None Material the patch is drawn with; it must use vertex colours. Empty uses the package’s vertex colour material.

Scripting API

Member Description
bool IsShown { get; } Whether the patch is drawn this frame.
Mesh PatchMesh { get; } The patch mesh, or null before it was first drawn.
static bool UsesGrid(VtBuildableDefinition buildable) Whether the patch shows for buildable: pieces that snap to the grid or to sockets.
void Redraw(VtBuildableDefinition buildable, Vector3 center) Draw the patch around center now.

VtBuildRangeIndicator

Component. Add it with Add Component → Vantage → Building → VtBuildRangeIndicator. Adds VtUnitBuilder automatically.

Draws the builder’s reach on the ground while a piece is being placed: a ring around the player with the piece’s VtBuildableDefinition.placementRange, in outOfRangeColor while the ghost is beyond it. The ring lies on the ground under it, following the VtCliffMap or, without one, the piece’s surface layers. Hidden for pieces without a range. Put it on the player next to the builder.

Inspector fields

Field Type Default Range Description
In Range Color (inRangeColor) Color #FFFFFF59 Ring colour while the ghost is in reach.
Out Of Range Color (outOfRangeColor) Color #F7595999 Ring colour while the ghost is out of reach.
Thickness (thickness) float 0.08 ≥ 0.01 Width of the ring in world units.
Material (material) Material None Material the ring is drawn with, tinted through _BaseColor or _Color. Empty uses a see-through unlit material.
Follow Ground (followGround) bool On Lay the ring on the ground under it. Off draws it flat at the player’s height.

Scripting API

Member Description
VtGroundCircle Ring { get; } The ring, or null before a piece with a range was placed.
bool IsShown { get; } Whether the ring is drawn this frame.

VtBuildSite

Component. Add it with Add Component → Vantage → Building → VtBuildSite.

A piece under construction. Attached to the placed instance when the buildable has a build time. Progress comes from AddBuildProgress, driven by whatever your game likes: a worker, a held key, or autoBuild for a piece that finishes on its own. On completion the site visual is swapped for the complete visual.

Inspector fields

Field Type Default Range Description
Total Seconds (totalSeconds) float 5 ≥ 0.01 Seconds of progress needed to complete. Set by the builder from the buildable’s Build Seconds.
Auto Build (autoBuild) bool Off Progress on its own, one second per second, without anyone working on it.
Site Visual (siteVisual) GameObject None Shown while under construction, hidden when done. A child of the prefab.
Complete Visual (completeVisual) GameObject None Hidden while under construction, shown when done. Start it deactivated in the prefab.

Scripting API

Member Description
bool IsComplete { get; } True once construction finished.
float Progress01 { get; } Progress from 0 to 1.
float SecondsRemaining { get; } Seconds of progress still needed.
event Action<float> OnBuildProgress Fires after every progress step with the new 0..1 progress.
event Action<VtBuildSite> OnBuildCompleted Fires once when the site completes.
event Action<VtBuildSite, bool> OnBuildCancelled Fires on Cancel with whether a refund was requested. The builder’s demolish handles refunds; this is for your own flows.
void Initialize() Apply the visual state. Idempotent; public for the late-attach path.
void AddBuildProgress(float seconds) Add seconds of progress. Authority-only; ignored once complete.
void Tick(float deltaTime) Advance autoBuild progress by deltaTime seconds.
void ApplyProgressFromNet(float seconds, float total) Mirror the authority’s progress: set it, raise OnBuildProgress when it changes, and complete when it reaches the total. Used by replication on clients; refused on the authority.
void Cancel(bool refundRequested) Signal that construction was abandoned. Fires OnBuildCancelled; nothing else changes.

VtBuildSocket

Component. Add it with Add Component → Vantage → Building → VtBuildSocket.

A connection point on a placed piece. Put one on each end of a wall prefab, facing outward; a buildable with VtBuildSnapMode.Socket and the same family snaps its ghost to the nearest one in reach, position and rotation, so walls line up without a grid.

Inspector fields

Field Type Default Description
Family (family) string "wall" Only buildables with the same family connect here, for example ‘wall’ or ‘fence’.

Scripting API

Member Description
static IReadOnlyList<VtBuildSocket> All { get; } Every enabled socket in the scene.
void Register() Make the socket findable. Called from OnEnable; idempotent.
void Unregister() Stop the socket from being found. Called from OnDisable; idempotent.
static VtBuildSocket FindNearest(string family, Vector3 point, float maxDistance, GameObject exclude) The closest registered socket of family within maxDistance of point, ignoring sockets under exclude. Null when none qualifies.

VtBuildPlacementRuleSet

Component. Add it with Add Component → Vantage → Building → VtBuildPlacementRuleSet.

Scene component that applies placement rules to every piece while it is enabled, such as a map’s “not on water” rule. Rules are registered with VtBuildPlacementRules on enable and removed on disable.

Inspector fields

Field Type Default Description
Rules (rules) VtBuildPlacementRule[] Empty Rules every piece must pass in this scene, in order. The first refusal is what the player sees.

Scripting API

Member Description
void RegisterRules() Register every rule in rules. Called on enable; call again after changing the list at runtime.
void UnregisterRules() Remove the rules this set registered.

VtPlacedBuildable

Component.

Marker the builder adds to every placed instance: which buildable it came from and who placed it. VtUnitBuilder.TryDemolish reads it to refund the cost, and All lists every enabled one for counting rules.

Inspector fields

Field Type Default Description
Definition (Definition) VtBuildableDefinition None The buildable this piece was placed from. Set by the builder.
Placed By (PlacedBy) VtUnitId — The unit that placed this piece. Set by the builder.
Paid From Stash Id (PaidFromStashId) string Empty Id of the shared stash that paid for this piece and gets the refund on demolish. Empty when the builder paid. Set by the builder.

Scripting API

Member Description
static IReadOnlyList<VtPlacedBuildable> All { get; } Every enabled placed piece in the scene. Destroyed pieces are dropped the next time it is read.
void Register() Make the piece countable. Called from OnEnable and by the builder; idempotent.
void Unregister() Stop counting the piece. Called from OnDisable; idempotent.

VtBuildableDefinition

Asset. Create it with Create → Vantage → Building → Buildable Definition.

Authored buildable: wall, chest, anvil, sapling, banner. VtUnitBuilder drives the whole placement lifecycle from it.

Inspector fields

General

Field Type Default Range Description
Id (id) string Empty Stable string identifier for save files and network payloads. Convention: ‘buildable..’.
Display Name (displayName) string Empty Name shown in the build menu.
Description (description) string Empty Description shown in the build menu tooltip.
Icon (icon) Sprite None Icon for the build menu and hotbar. Optional.
Icon Id (iconId) string Empty Name of an icon from the package’s icon set, used when Icon is empty. Optional.
Sort Weight (sortWeight) int 0 Order within its category: lower comes first. Pieces with the same weight keep their list order.

Classification

Field Type Default Range Description
Category (category) VtBuildableCategoryDefinition None Category for build-menu sorting and tinting. Optional.

Spawned Object

Field Type Default Range Description
Prefab (prefab) GameObject None Prefab spawned on placement. Must contain a VtUnit.
Ghost Prefab (ghostPrefab) GameObject None Optional preview prefab. Empty clones the real prefab as the ghost.

Cost

Field Type Default Range Description
Item Cost (itemCost) VtRecipeIngredient[] Empty Items paid on placement, from the builder’s bag or the shared stash that pays for it. Empty = free.
Currency Cost (currencyCost) VtCurrencyAmount[] Empty Currency paid on placement, from the builder’s wallet or the shared stash that pays for it.

Snap & Footprint

Field Type Default Range Description
Snap Mode (snapMode) VtBuildSnapMode Grid Free = raw cursor. Grid = nearest cell. SurfaceAligned = tilt to the surface. Socket = the nearest socket of the same family within reach, otherwise the grid.
Grid Cell Size (gridCellSize) float 0 ≥ 0 Cell size in world units for Grid and Socket snapping. 0 uses the scene VtWorldGrid’s build cell: its Cell Size divided by Build Subdivisions.
Footprint Cells (footprintCells) Vector2Int (1, 1) Cells the piece covers on the grid, X by Z at zero rotation. Even counts align to cell edges so a 2×1 wall sits between cell centres.
Rotation Step Degrees (rotationStepDegrees) float 90 ≥ 0 Degrees per rotate step while placing. 0 disables rotation.
Socket Family (socketFamily) string "wall" Socket family this piece connects to when Snap Mode is Socket. Match the family on the prefab’s VtBuildSocket components.
Socket Snap Distance (socketSnapDistance) float 1.5 ≥ 0 How far from the cursor a socket may be and still snap.
Placement Range (placementRange) float 8 ≥ 0 How far from the builder a piece may be placed, in world units on the ground plane. 0 = anywhere. The authority refuses placements past this plus the interact tolerance.
Surface Mask (surfaceMask) LayerMask Everything Layers the cursor ray hits to find a placement point. Typically ground and terrain.
Footprint Half Extents (footprintHalfExtents) Vector3 (0.5, 0.5, 0.5) Half extents of the box the placement check sweeps. Match the prefab’s bounds.
Forbidden Overlap Mask (forbiddenOverlapMask) LayerMask Everything Layers whose colliders block placement when they overlap the footprint. Exclude the ground.
Allow Overlap With Units (allowOverlapWithUnits) bool Off Ignore overlaps with units. For banners and ground markers.
Placement Rules (placementRules) VtBuildPlacementRule[] Empty Checks of your own this piece must pass, after the built-in ones and the scene’s rules. Examples: near a camp, at most one per player.

Build Time

Field Type Default Range Description
Build Seconds (buildSeconds) float 0 ≥ 0 Construction time. 0 spawns the finished piece. Above 0 attaches a VtBuildSite that needs progress.

Prerequisites

Field Type Default Range Description
Required Level (requiredLevel) int 0 ≥ 0 Minimum builder level. 0 = no gate.
Required Completed Quests (requiredCompletedQuests) VtQuestDefinition[] Empty Quests that must be turned in before this buildable is offered.
Required Items (requiredItems) VtRecipeIngredient[] Empty Items the builder must carry but that are not consumed, such as a hammer.
Required Unlock (requiredUnlock) VtUnlockDefinition None Unlock that must be owned, by the builder or the shared stash that pays for it. Empty = no unlock gate.

Refunds

Field Type Default Range Description
Refund On Cancel (refundOnCancel) bool On Demolishing an unfinished build site returns the full cost.
Demolish Refund Fraction (demolishRefundFraction) float 1 0 to 1 Fraction of the cost returned when a finished piece is demolished. 1 = everything, 0 = nothing.

VtBuildableCategoryDefinition

Asset. Create it with Create → Vantage → Building → Buildable Category.

A build-menu category such as Walls, Furniture, Workstations or Storage. Sorts and tints the build menu. Create one asset per category.

Inspector fields

Field Type Default Description
Id (id) string Empty Stable string identifier for DB / network payloads. Convention: ‘buildable.category.walls’, ‘buildable.category.furniture’. Required.
Display Name (displayName) string Empty UI display name. E.g. ‘Walls’, ‘Furniture’, ‘Workstations’.
Description (description) string Empty Designer-facing description.
Sort Weight (sortWeight) int 0 Sort priority for build-menu UI ordering. Lower = appears first. Convention: Walls 0, Furniture 100, Workstations 200, Storage 300. Leave gaps for inserts.
Color (color) Color #FFFFFFFF UI tint applied to the buildable’s name / category label in the build menu.
Icon (icon) Sprite None Optional category icon shown in the build-menu UI.
Icon Id (iconId) string Empty Name of an icon from the package’s icon set (VtIcons), used when Icon is empty. Optional.

VtNearTaggedUnitRule

Asset. Create it with Create → Vantage → Building → Rules → Near Tagged Unit. Inherits VtBuildPlacementRule.

Placement rule: the piece must be within radius of a living unit with tag, such as “only near a camp”. With invert it must be farther away than that, such as “not near an enemy base”. Distance is measured on the ground plane from the placement point. The builder itself never counts.

Inspector fields

Field Type Default Range Description
Reason Key (reasonKey) string Empty Localization key or plain text shown when this rule refuses. Empty shows the generic ‘You cannot build here’.
Tag (tag) VtUnitTagDefinition None Tag the unit must carry. Empty = the rule always passes.
Radius (radius) float 10 ≥ 0 Distance on the ground plane, in world units.
Same Faction Only (sameFactionOnly) bool Off Only units of the builder’s faction count.
Count Unfinished (countUnfinished) bool Off Build sites that are not finished yet count too.
Invert (invert) bool Off Refuse near such a unit instead of requiring one.

VtMaxPlacedRule

Asset. Create it with Create → Vantage → Building → Rules → Max Placed. Inherits VtBuildPlacementRule.

Placement rule: at most maxCount pieces of the buildable being placed may stand, counted for the builder alone or for the whole world. Demolished and destroyed pieces stop counting.

Inspector fields

Field Type Default Range Description
Reason Key (reasonKey) string Empty Localization key or plain text shown when this rule refuses. Empty shows the generic ‘You cannot build here’.
Max Count (maxCount) int 1 ≥ 1 How many of this piece may stand at once.
Scope (scope) VtMaxPlacedRule.CountScope PerBuilder Per Builder counts the builder’s own pieces; World counts everyone’s.

VtBuildPlacementRule

Abstract asset base. Shipped subclasses: VtMaxPlacedRule, VtNearTaggedUnitRule.

Base for placement rules authored as assets. Subclass it, implement Check, and add a CreateAssetMenu; list the asset on a buildable’s VtBuildableDefinition.placementRules or on a VtBuildPlacementRuleSet. reasonKey is what the player reads when the rule refuses.

Inspector fields

Field Type Description
Reason Key (reasonKey) string Localization key or plain text shown when this rule refuses. Empty shows the generic ‘You cannot build here’.

Scripting API

Member Description
virtual bool Allows(in VtBuildPlacementContext context, out string refusalKey) True when Check passes; otherwise false with reasonKey as the refusal. Override it only when the refusal text depends on the placement.
protected abstract bool Check(in VtBuildPlacementContext context) True when the placement is allowed.

IVtBuildPlacementRule

Interface. Implemented by VtMaxPlacedRule, VtNearTaggedUnitRule.

A check of your own on where a piece may be placed, such as “not on water” or “only near a camp”. The builder asks every rule for the preview each frame and again when the placement is committed, after its own checks. List rules on a buildable’s VtBuildableDefinition.placementRules, or register them for every piece with VtBuildPlacementRules.Register or a VtBuildPlacementRuleSet in the scene.

Scripting API

Member Description
bool Allows(in VtBuildPlacementContext context, out string reasonKey) True when the placement is allowed. Otherwise set reasonKey to a localization key or plain text for the player, or leave it empty for the generic text.

IVtBuildCursorProvider

Interface. Implemented by VtScreenCursorProvider.

Where the placement cursor points in the world, for VtUnitBuilder. The default, VtScreenCursorProvider, raycasts from the main camera through the mouse position. Implement it for a gamepad cursor, touch or VR, and hand it to VtUnitBuilder.SetCursorProvider.

Scripting API

Member Description
bool TryGetCursorWorldPoint(LayerMask surfaceMask, out Vector3 worldPoint, out Vector3 surfaceNormal) The world point and surface normal under the cursor on a surface in surfaceMask. False when the cursor points at no such surface, such as off-screen or at the sky. Called every frame while placing; must not change any state.

VtBuildPlacementContext

Struct.

Everything a IVtBuildPlacementRule is told about a placement: who builds what, where, and whether this is the preview or the placement that pays.

Scripting API

Member Description
Vector2Int FootprintCells { get; } Cells the piece covers, X by Z at zero rotation.
float CellSize { get; } Edge of one footprint cell in world units: the buildable’s own cell size, else the scene grid’s.
GameObject Ghost { get; } The builder’s placement preview, or null. Rules that look for nearby units skip it.
readonly VtUnitBuilder Builder The builder asking.
readonly VtUnit Unit The unit that builds.
readonly VtBuildableDefinition Buildable The piece being placed.
readonly Vector3 Position Where the piece goes.
readonly Quaternion Rotation The piece’s rotation.
readonly float Yaw Rotation around the up axis in degrees. When the server places for a client, it is read from Rotation, so a piece tilted to a slope can report a slightly different value than the client’s preview did.
readonly float RangeTolerance Extra distance a range check should allow. 0 for the preview; the interact tolerance from VtTuning when the placement is committed, so a player at the edge of range is not refused by a small position difference on the server.
readonly bool IsCommit False while the ghost is previewed, true when the placement is committed and paid. A rule that depends on state only the server has returns true in the preview and decides on commit.
bool IsPartOfGhost(Component target) True when target belongs to the placement preview.
void GetFootprintCellCenters(List<Vector3> centers) Clear centers and fill it with the world centre of every footprint cell, at the placement’s height. Quarter turns swap the footprint’s X and Z.

VtBuildRefusal

Struct.

Why a placement is refused: a VtBuildFailureReason plus, when a placement rule refused, the rule’s localization key. VtFailureText.Describe turns it into the text to show. Converts to VtBuildFailureReason where only the reason matters.

Scripting API

Member Description
bool IsNone { get; } True when nothing refused.
static readonly VtBuildRefusal None No refusal: the placement passes.
readonly VtBuildFailureReason Reason The reason. VtBuildFailureReason.RefusedByRule when a placement rule refused.
readonly string RuleKey Localization key or text from the rule that refused. Empty for built-in reasons and for rules without a key of their own.
static VtBuildRefusal ByRule(string ruleKey) A refusal by a placement rule with its localization key.

VtBuildPlacementRules

Static class.

Placement rules that apply to every piece, and the check that runs them. Register a rule from code, or put a VtBuildPlacementRuleSet in the scene. Global rules run in the order they were registered, before the buildable’s own VtBuildableDefinition.placementRules; the first refusal wins.

Scripting API

Member Description
static IReadOnlyList<IVtBuildPlacementRule> Global { get; } Rules that apply to every piece, in the order they run.
static void Register(IVtBuildPlacementRule rule) Apply rule to every piece. Registering a rule twice does nothing.
static void Unregister(IVtBuildPlacementRule rule) Stop applying a rule added with Register.
static bool Check(in VtBuildPlacementContext context, out VtBuildRefusal refusal) Run the global rules, then the buildable’s own. False with the first refusal when one refuses.

Enums

VtBuildFailureReason

Why a builder call was refused or a placement is invalid.

Value Description
None Nothing refused: the call succeeded or the placement is valid.
BuildableNull No buildable was given, or it has no prefab.
MissingItems The builder cannot pay the buildable’s item cost.
MissingCurrency The builder cannot pay the buildable’s currency cost.
MissingRequiredItems The builder does not carry the buildable’s required items, such as a hammer.
LevelTooLow The builder’s level is below the buildable’s required level.
MissingPrereqQuests A quest the buildable requires has not been turned in.
BlockedByCollider A collider on the buildable’s forbidden overlap layers is in the way.
NoSurface The cursor points at no surface the piece can stand on.
AlreadyPlacing A placement is already in progress.
NotPlacing Nothing is being placed.
AuthorityNotLocal This copy is not the authority. VtUnitBuilder.TryPlace and VtUnitBuilder.TryDemolish send the request to the authority, which decides.
NoBuilderComponent The unit has no builder component.
NotABuildable The target of a demolish is not something this system placed.
CrossesCliff The footprint spans more than one cliff level or lies on a ramp.
OutOfRange The placement point is farther from the builder than the buildable’s placement range.
Locked The buildable’s VtBuildableDefinition.requiredUnlock is not owned.
BlockedGround The footprint covers a cell the cliff map marks as blocked.
RefusedByRule A placement rule refused. VtBuildRefusal.RuleKey carries the rule’s own reason.

VtKeepPlacing

Whether VtBuildInput starts placing the same building again after one is placed.

Value Description
Never Placing ends after every building.
WhileModifierHeld Placing goes on while the keep-placing modifier, Shift by default, is held.
Always Placing goes on until it is cancelled or the next building cannot be paid for.

VtOutOfReachPlacement

What VtBuildInput does when the player places a piece beyond its placement range.

Value Description
Refuse Refuse with VtBuildFailureReason.OutOfRange. The player walks closer and places again.
WalkThere Hold the ghost where it is, walk the player into range and place it there on arrival.

VtBuildGhostLook

How VtBuildGhostStyle colours the placement ghost.

Value Description
Auto Tint when the buildable has its own ghost prefab, ReplaceMaterials when the ghost is a copy of the real prefab.
Tint Keep the ghost’s own materials and tint them through _BaseColor and _Color. Suits a ghost prefab whose materials are already see-through.
ReplaceMaterials Draw every part of the ghost with one see-through material in the valid or the refused colour.

VtBuildSnapMode

How the cursor maps to a buildable’s placement transform.

Value Description
Free The raw cursor point, upright.
Grid Nearest cell on the ground grid, upright. Even footprints align to cell edges.
SurfaceAligned The cursor point with the up axis aligned to the surface normal.
Socket The nearest VtBuildSocket of the same family within reach, otherwise the grid.

VtMaxPlacedRule.CountScope

Whose pieces count toward the limit.

Value Description
PerBuilder Only pieces the builder placed.
World Every placed piece of the buildable, whoever placed it.