SwarmTarget¶
namespace MassiveSwarmSystem.Runtime
A MonoBehaviour that marks a GameObject as something the swarm chases: the player, a
decoy, an objective. Add it to any GameObject and the swarm picks it up automatically; no
manager reference is required.
Setting it up in the Inspector
This page is the scripting view of SwarmTarget. If you just want to drop the
component on a GameObject and tune it in the Inspector, see
Targets instead.
How it registers¶
While the component is enabled it registers its Transform with the active
SwarmManager; when disabled or destroyed it unregisters
itself. You never wire up a reference by hand.
- Registration happens on
OnEnable. The component runs atDefaultExecutionOrder(-900), which puts it just after the manager at-1000and ahead of your own scripts at the default0, so a target is on the books before any gameplay code asks about it. - If no manager exists yet when the target enables, registration is retried once in
Start. - The manager can track several targets at once and switches between them with hysteresis. See Max Active Target Count.
The common runtime patterns need no manager calls at all:
using MassiveSwarmSystem.Runtime;
using UnityEngine;
public class DecoyController : MonoBehaviour
{
// Spawn a temporary distraction the swarm will chase.
public GameObject SpawnDecoy(GameObject prefab, Vector3 position)
{
GameObject decoy = Instantiate(prefab, position, Quaternion.identity);
// Adding the component (on an active GameObject) fires OnEnable, which
// registers the decoy with the active SwarmManager automatically.
decoy.AddComponent<SwarmTarget>();
return decoy;
}
// Disabling or destroying the target unregisters it; agents fall back to
// whatever targets remain.
public void ReleaseDecoy(GameObject decoy) => Destroy(decoy);
}
Body radius¶
SwarmTarget resolves a body radius: how wide the target's body is, in world units,
that the swarm uses to surround and stop around it. The value is computed from colliders
(or an explicit number) and then cached, so the target snapshot taken every simulation step never walks
colliders.
The auto-detect rules and the Inspector fields are described in full on the Targets page. From code, the resolved value is read-only:
SwarmTarget target = GetComponent<SwarmTarget>();
float radius = target.BodyRadius; // resolved radius, world units
if (target.RadiusSource == SwarmTarget.BodyRadiusSource.AutoDetect && !target.HasDetectedSource)
{
// Auto Detect found no collider or CharacterController to measure,
// so BodyRadius is the 0.5 fallback. Add a Capsule/Box sized to the body.
Debug.LogWarning($"{name}: swarm target has no measurable collider.", this);
}
Recompute after changing colliders at runtime
BodyRadius is cached at OnEnable / OnValidate. If you resize, add, or remove a
collider while the game is running, call RefreshBodyRadius() so the swarm sees the new
size:
Public API¶
The body-radius properties (RadiusSource, IncludeChildColliders, ManualBodyRadius, BodyRadius, HasDetectedSource) are read-only from code. Configure them through the Inspector. RefreshBodyRadius() is the one mutating entry point for that group.
Priority and SelectionRadius are runtime-settable: you can write to them from code while the game is running and the swarm picks the new value up on its next simulation step.
| Member | Type | Description |
|---|---|---|
Priority |
float (get/set) |
How strongly the swarm prefers this target: 1 is normal, and higher pulls more agents. Setter clamps to SwarmManager.MinPriority and pushes the new value to the manager when registered; it applies on the next simulation step. |
SelectionRadius |
float (get/set) |
Reach in world units within which this target attracts agents; 0 means unlimited. Setter clamps to >= 0. Live-resolved each tick. |
RadiusSource |
BodyRadiusSource |
How BodyRadius is resolved: AutoDetect from colliders, or Manual from an explicit value. |
IncludeChildColliders |
bool |
When auto-detecting, whether child colliders are also measured. A CharacterController on a child counts as one of those colliders, measured from its bounds. With this off, only this GameObject's own colliders and CharacterController count. |
ManualBodyRadius |
float |
The explicit radius, in world units, used only when RadiusSource is Manual. |
BodyRadius |
float |
The resolved radius, in world units. Falls back to 0.5 when auto-detect finds nothing measurable. A Manual radius of 0 reads back as 0 here, but the swarm treats it as 0.5. |
HasDetectedSource |
bool |
true when auto-detect found a usable collider or CharacterController. false in Manual mode, or when nothing was found and BodyRadius is the 0.5 fallback. |
RefreshBodyRadius() |
void |
Recomputes and caches BodyRadius from the current settings. Call after changing colliders at runtime. |
Handle |
SwarmTargetHandle |
A stable name for this target while it is registered, and default while it is not. Store this instead of a registered index: an index shifts down when an earlier target unregisters and quietly starts naming its neighbour. Disabling and re-enabling the component mints a fresh handle and retires the old one, which then resolves to nothing. Pass it to the SwarmManager target methods to read the target back. |
BodyRadiusSource¶
public enum BodyRadiusSource
{
AutoDetect = 0, // measure from colliders / CharacterController on this GameObject (and children when Include Child Colliders is on)
Manual = 1, // ignore colliders and use ManualBodyRadius
}
Quick reference in your IDE
Key members carry a short XML summary, so hovering them in Visual Studio or Rider shows a one-line description while you code. This page has the full detail.
Related¶
- Targets: Inspector setup, the body-radius gizmo, and common target patterns.
- Swarm Manager: Target Selection: how the manager chooses and switches between registered targets.
- Attack Profile: reach calculations that consume the body radius set here.
- FAQ: my player climbs on top of the agents: what to do when the target is a
CharacterControllerand agent bodies lift it.