Transform & Revert
The base loop. Transform Into Prop reads the prop the character is currently looking at — no dropdown, no target to pick — so both triggers can sit on the same key, separated only by the condition.
On Key Down (E) + Can Clone Prop = true -> Transform Into Prop (Self)
On Key Down (E) + Is Disguised = true -> Revert To Character (Self)Switching directly from one prop to another is supported: the player does not have to revert first. If you want a fixed disguise instead — a scripted cutscene, a saved loadout, a network message — use Transform Into Prop (by ID) and drag the definition into the Prop ID getter rather than typing a GUID.
Hunter Damage
The asset applies no damage itself. What a guess costs is authored on the instruction that applies it, so there is exactly one number and it is the one that runs.
Prop-side (recommended)
On Was Found fires on the prop player who was identified, so no hunter-side routing is needed — and the same wiring is correct in multiplayer.
─ On the hider prefab ─────────────────────────────────────
On Was Found + Is Round Phase = Hunt
-> Deal Damage Target = Self Stat = Health Amount = 100
─ On the hunter prefab ────────────────────────────────────
On Wrong Guess
-> Deal Damage Target = Self Stat = Health Amount = 25From a melee hit instead of a raycast
If your hunters swing a weapon rather than press an inspect key, evaluate the struck object instead of firing a ray. Place the trigger on the object that was hit.
On Melee Hit (on the world prop or the character)
-> Hunter Inspect Target
Hunter: Target (GC2 passes the attacker)
Inspected: SelfDamage through a disguise
Deal Damage to Prop Player routes damage to whoever is currently wearing a struck world prop, and is a silent no-op if nobody is. On a plain character trigger it applies the damage directly.
On Melee Hit (on a world prop)
-> Deal Damage to Prop Player Prop = Self Stat = Health Amount = 100Camera Framing That Adapts to the Prop
A shot framed for a 1.8 m character is wrong for a 0.4 m crate and wrong again for a 4 m tree. No extra component and nothing to keep in sync — the package exposes the dimensions it already measures, and Game Creator's own Change Aim instruction consumes them.
─ Adapt on transform ──────────────────────────────────────
On Transform Complete
-> Change Aim
Shot = your third-person Shot Camera
Offset Lift = Prop Size ▸ Height × 0.15
Offset Radius = Prop Size ▸ Bounding Radius × 1.0
Duration = 0.3
─ Restore on revert ───────────────────────────────────────
On Reverted
-> Change Aim
Shot = the same Shot Camera
Offset Lift = 0
Offset Radius = 0
Duration = 0.3Change Aim's inputs are offsets, added on top of what is authored on the shot every frame — so reverting is just zero. No cached state, nothing to get out of sync, and no risk of a disguise leaving the camera permanently displaced if a player disconnects mid-round.
| Prop Size measurement | What it is | Typical use |
|---|---|---|
| Height | Full height above the floor | Lift — raise the camera on tall props |
| Width (X) / Depth (Z) | Footprint on one axis | Asymmetric framing |
| Footprint | The wider of X and Z | Radius when only ground size matters |
| Bounding Radius | Half-diagonal of the whole prop | Radius — grows with both height and width |
Not disguised? You get zero. Prop Size returns 0 when the target has no controller, is not disguised, or has just reverted — and with additive offsets, zero means "leave the shot as authored". The safe value and the neutral value are the same number, so there is no failure mode where a stale measurement strands your camera.
Lean, Rotate & Whistle
The three things that turn hiding from a state into a skill. All three need Prop Clone Motion or Prop Whistle on the hider, and all three reset themselves on revert.
Lean and rotate — one trigger per key press
On Key Down (Q) + Is Disguised = true -> Lean Prop Self Lean X: -1
On Key Down (E) + Is Disguised = true -> Lean Prop Self Lean X: +1
On Key Down (R) + Is Disguised = true -> Rotate Prop Self Degrees: 45PropCloneMotion.SetLeanInput(Vector2) from your own script instead — that overload sets the value rather than adding to it. Passing Vector2.zero returns the prop smoothly to upright.Whistle, and the hunter reacting to it
─ On the hider ────────────────────────────────────────────
On Key Down (F) + Is Disguised = true
+ Is Whistle On Cooldown = false
-> Play Whistle Self
─ On the hunter ───────────────────────────────────────────
On Hunter Hears Whistle
-> your directional indicator, alert sound, or AI reactionOn Hunter Hears Whistle fires on the hunter only when the whistle happens within the configured range. The lower-level On Whistle event fires for every whistle regardless of distance, and carries the world position — do your own range check in the condition if you use that one.
A Full Round Loop
Registration, start, elimination, result, restart. Registration is deliberately explicit: nothing joins a round by existing.
─ On each hider ───────────────────────────────────────────
On Start
-> Register Prop Player Hider = Self
On Vital Depleted (Target = Self)
-> Mark Prop Eliminated Target = Self
-> Report Prop Eliminated Eliminated = Self
─ On a scene-level object ─────────────────────────────────
On Start (or a Start button)
-> Reset All Stats (each hider)
-> Start Round
On Round State Changed + Is Round Phase = Hunt
-> Move To Spawn Point Target = <hunter> Spawn Point = Prop Player
On Hunters Win -> show your "hunters win" screen
On Props Win -> show your "props win" screenFor the scoreboard, bind Props Alive and Props Registered into a label for an "x of y remaining" display, Round Number for the match counter, and Round Timer (mm:ss) for the clock — none of which needs a script.
Lobby Board UI
The package ships three sample view components under Samples/BasicHideAndSeek/UI/: Lobby Board (the root panel), Player Row (one row per prop player) and Round Timer Display. They are pure views — all data comes from Round System and Transform Controller events, so you can replace the prefab visuals without touching the scripts.
Canvas (Screen Space - Overlay, Canvas Scaler at 1920x1080)
+-- LobbyPanel <- LobbyBoard component here
+-- StateLabel (Text)
+-- RoundNumberLabel (Text)
+-- PropsAliveLabel (Text)
+-- TimerLabel (Text) <- RoundTimerDisplay here
+-- PlayerListScroll (Scroll View)
+-- Content (Vertical Layout Group + Content Size Fitter)
+-- PlayerRow (prefab, instantiated one per player)
+-- NameLabel · PropIcon · AliveIndicator · EliminatedIndicatorNothing to wire for the player list. The board mirrors the round's own roster: on enable it rebuilds from RegisteredPropPlayers, then keeps itself in step through the register and unregister events. A panel that starts inactive and is revealed mid-round therefore shows the correct list the moment it appears, and alive/eliminated badges are re-read on every refresh, so starting a new round un-marks every row without the board tracking anything itself.
Saving Prop Choices
Nothing in the package persists, deliberately — see Core Concepts. What you usually want to save is your own content: which props a player has unlocked, cosmetics, match history. The durable handle for all of it is Prop Definition ID.
─ Saving ──────────────────────────────────────────────────
Current Prop ID (property getter) -> a GC2 Global Variable
-> a Remember / Memory component
─ Restoring ───────────────────────────────────────────────
On Start (after the load)
-> Transform Into Prop (by ID)
Target: Self
ID: <the saved string, or the Prop ID getter>The ID is a stable GUID generated once, never changed, guarded against duplication, and safe in a save file or a network payload. Store the strings and look the definitions back up through the registry at load time.