Class AICombatDecision
The single combat decision shared by every attacking state.
public static class AICombatDecision
- Inheritance
-
AICombatDecision
- Inherited Members
Remarks
Melee, ranged, caster, healer, defender and rogue states previously each carried their own
near-identical TryAttack override — five copies of "am I too close? can I cast? do I
walk in?" that drifted apart from one another and could only be verified by playing the
game. They now all funnel through Plan(in AICombatContext) and differ purely in the numbers they
feed it and in what they do with the resulting intent.
Because this is a pure function over plain floats, an archetype asset's behaviour is
directly assertable in an EditMode test — see AICombatDecisionTests and
AIArchetypeAssetTests.
Fields
ENGAGE_SLACK
Multiplier applied to the engagement distance before the NPC bothers closing in. Without the slack the NPC oscillates between "one centimetre too far" and "stop".
public const float ENGAGE_SLACK = 1.1
Field Value
RANGE_APPROACH_FACTOR
Fraction of an ability's range the NPC actually walks to. Stopping exactly at maximum range means the first step the target takes puts the NPC out of range again.
public const float RANGE_APPROACH_FACTOR = 0.9
Field Value
RANGE_HYSTERESIS
How far past its ability range a target may drift before an already-attacking NPC gives up and closes again.
public const float RANGE_HYSTERESIS = 1.1
Field Value
Remarks
Without this the decision at the range boundary is a bare distance <= range,
and a target strafing around that boundary flips the NPC between Attack and
CloseDistance on alternating ticks. Each flip toggles NavMeshAgent.isStopped, and
because the agent has acceleration and braking it never reaches speed in either
direction — the NPC visibly shudders in place instead of either fighting or chasing.
Ten percent is enough to absorb a strafing player without letting the NPC attack from meaningfully outside its stated range.
Methods
Plan(in AICombatContext)
Decides what the NPC should do about its target this tick.
public static AICombatPlan Plan(in AICombatContext context)
Parameters
contextAICombatContextThe measured combat situation.
Returns
- AICombatPlan
The intent plus the distance the movement intents should aim for.
ResolveApproachDistance(in AICombatContext, float)
Where to stop when walking an out-of-range ability into range.
public static float ResolveApproachDistance(in AICombatContext context, float engageDistance)
Parameters
contextAICombatContextThe measured combat situation.
engageDistancefloatThe archetype's engagement distance.
Returns
- float
The distance from the target at which to stop moving.
Remarks
Approaches to a fraction of the ability's range so a moving target does not immediately step back out, but never closer than the archetype's engagement distance — a caster with a 30 m nuke and a 20 m preferred distance stops at 20, not at 27. A melee archetype (no preferred distance) is allowed to close all the way.
ResolveEngageDistance(in AICombatContext)
The distance this archetype wants to sit at: its preferred distance, or melee reach when it has none.
public static float ResolveEngageDistance(in AICombatContext context)
Parameters
contextAICombatContextThe measured combat situation.
Returns
- float
A strictly positive engagement distance.