Building Hunter and Props Systems for Games
The Basics of Hunter And Props
A hunter and props system is really just a structured way to handle how a player-controlled or AI-controlled entity finds, tracks, and interacts with objects in a game world. The hunter part is the agent doing the searching. The props are the static or semi-static objects scattered through the environment that carry relevance—things like cover points, collectibles, interactables, or clues. When people talk about building one, they're usually trying to avoid the mess that comes from scattering collision triggers and hard-coded references everywhere. I usually start with a tagged prop system. Every prop gets a MonoBehaviour that implements a common interface, say IProp. That interface has a few methods: OnDiscovered, OnInteract, OnDespawn. Then the hunter has a component that sweeps the area—either radius-based using Physics.OverlapSphere or a line-of-sight raycast loop depending on whether your game is tactical or arcade-y. The hunter queries active props within range, runs a filter for visibility or tag matching, and calls OnDiscovered on the results. The trick most people skip is making the prop lifecycle stateful. A prop isn't just found and done. It needs states: undiscovered, observed, interacted, consumed, destroyed. If you're building this for a stealth game, an observed prop that hasn't been interacted with yet might alert enemies if the hunter lingers too long near it. If you're building it for a collectathon, observed just means highlighted. The difference matters a lot more than the setup itself.
Implementation Details
Here is a practical setup I tend to use. First, create a central PropRegistry singleton. When any prop spawns, it registers itself. When it despawns, it unregisters. The hunter doesn't scan the scene itself. It asks the registry for props in range. This cuts physics overhead significantly because you're not firing OverlapSphere every frame over the entire scene. You're querying a curated list. On the prop side: Each prop holds a reference back to the registry. It has a bounds volume defined either by a Collider component or a manually set radius. The registry stores these bounds for spatial queries. When the hunter calls the registry's GetPropsInBounds method, it returns only the props whose bounds intersect the hunter's query volume.
On the hunter side: The hunter updates its query interval based on context. In a calm exploration state, you might check every half second. In a combat state, every frame or every tenth of a second. The registry call is cheap, but doing it unnecessarily burns cycles. Don't over-query. For interaction, I route everything through the PropRegistry as well. The hunter requests an interaction with a specific prop GUID, the registry verifies it's still valid and in an interactable state, then calls the prop's OnInteract method. This prevents the hunter from interacting with props that have already been despawned or consumed, which is a surprisingly common source of null reference exceptions in early builds.
Get the Full Details

A Real Problem I Encountered
I was working on a prototype where props had persistent states across scene loads. A prop like a locked chest or a blood trail needed to remember whether it had been opened or followed. The initial approach stored state on the prop GameObject itself using DontDestroyOnLoad, which worked fine until I tested with multiple players in a shared session. Each instance of the scene carried its own copy of the prop registry, and the states drifted apart. One player saw an open chest while the other saw it closed. The workaround was moving the persistent state out of the prop GameObject and into a dedicated StateBridge component that lived in a persistent manager scene. The bridge held a dictionary keyed by prop GUID, mapping to a serializable state struct. When a new scene loaded, each prop in that scene looked up its GUID in the bridge and restored its previous state. The bridge never reloaded. This meant all instances in a shared session stayed synchronized because they all read from the same source of truth. This also solved a secondary issue where prop IDs would collide when two identical props of the same type spawned in different scenes. Each prop now generates its GUID at editor time using a unique ID generator, not at runtime. Runtime-generated IDs are cheap but they can duplicate, especially in pooled systems.
When Hunter And Props Breaks Down
There are scenarios where this architecture is the wrong call. If your game has hundreds or thousands of props that are purely visual and don't need interaction logic, the registry approach adds unnecessary overhead. A simple layer-based collision check or a broad-phase spatial hash is faster and uses less memory. The registry system shines when prop interactions are meaningful and sparse, not when the world is just cluttered with decorative items. Another limitation is networked multiplayer without authority. If the hunter is client-side and props are server-authoritative, you need to handle the fact that the client's view of prop states will lag behind reality. The cleanest fix is server-driven state replication with client-side prediction on the hunter's queries. The alternative—letting clients trust their own prop state—is fast but breaks immediately if two players interact with the same prop at the same time.
Common Mistakes to Avoid
People often make the prop interaction synchronous when it shouldn't be. A prop like a vending machine or a terminal might need to trigger a sequence, play an animation, wait for a timer, then update state. If OnInteract blocks the hunter's update loop waiting for that sequence to finish, the whole system feels sluggish. Use coroutine-based or state-machine-driven interaction flows instead. Let the prop handle its own timeline. Another mistake is not accounting for occlusion. A prop might be within the hunter's radius but behind a wall. If your system only checks distance and not visibility, the hunter will start interacting with objects it can't actually see. A simple visibility check using a raycast from the hunter's sensor point to the prop's center before calling OnDiscovered solves this without much cost.

Quick Reference
If you want a starting point, the general pattern is straightforward enough to implement without external assets. You need three things: a registry to track props and their bounds, an interface or base class that defines how props behave, and a hunter component that queries the registry and triggers interactions through it. That's the core. Everything else—states, persistence, network syncing—is built on top of that foundation. For a ready-made version, you can find community implementations on the Unity Asset Store and GitHub. Search for "prop system" or "interactive object manager." Most free implementations are functional but lack persistence and networking support. If you need those features out of the box, the paid packages tend to be more complete, though they also carry more overhead you may not need.