C++ Rapid-Fire & Duplicate Watchdogs
In Unreal Engine projects utilizing the Gameplay Ability System (GAS), rapid duplicate triggers and accidental effect stacking are among the hardest bugs to track down. Specter embeds C++ Rapid-Fire Watchdogs directly into the engine-level USpecterSubsystem to catch non-human, duplicate activations the microsecond they happen.
How the Watchdogs Work
Integrated directly into USpecterSubsystem, Specter attaches hooks to every registered UAbilitySystemComponent (ASC). Instead of waiting for downstream assertions to fail, the watchdogs track activation and application delta timestamps on the game thread.
[Specter Watchdog][Server] Rapid duplicate ability activation detected on 'BP_Hero_Steel_C_1'! Ability 'Ability.Slot.Q' activated twice within 12.4ms! Check for duplicate triggers or missing DoOnce!
[Specter Watchdog][Server] Rapid duplicate effect application detected on 'BP_Hero_Steel_C_1'! Effect 'GE_Howitzer_BasicAttack' applied twice within 8.2ms!Detection Thresholds
| Watchdog | Threshold | Common Root Cause |
|---|---|---|
| Ability Activation Watchdog | < 50 ms | Missing DoOnce node in input handler, duplicate server RPC dispatch, or button bounce. |
| Gameplay Effect Watchdog | < 25 ms | Double projectile overlap triggers, overlapping notify states in animation montage, or missing collision channel filter. |
Why These Thresholds?
Even in high-refresh competitive titles running at 120+ FPS, human input reaction cannot intentionally trigger an ability twice within 50 milliseconds. Similarly, applying the exact same instant Gameplay Effect twice within 25 milliseconds almost always signifies an engine-side logic error rather than intentional gameplay.
What Happens When a Threshold is Breached?
When a rapid-fire duplicate event is detected, Specter performs three automated actions simultaneously:
- Unreal Engine Console Warning: Emits an explicit warning log with actor, ability/effect class, and exact delta (e.g.
[Specter Watchdog][Server] Rapid duplicate ability activation detected on 'Hero'! activated twice within 12.4ms!). - Real-Time WebSocket Broadcast: Dispatches a
DiagnosticWarningevent packet directly to connected test runners. - Flight Recorder Telemetry: Records the anomaly into the persistent C++ in-memory ring buffer (
TelemetryLog) for automated test reports.
Asserting Watchdog State in Tests
You can listen to DiagnosticWarning events in your Playwright test files to ensure your abilities do not spam the engine with duplicate triggers:
import { test, expect } from '@specter-automation/test';
test('Ability execution does not trigger rapid-fire duplicate warnings', async ({ world }) => {
const steel = world.actor('BP_Hero_Steel');
// Collect real-time diagnostic warnings from the engine subsystem
const warnings: any[] = [];
world.on('DiagnosticWarning', (warning) => {
warnings.push(warning);
});
// Execute gameplay input
await steel.pressKey('Q');
await expect(steel).toHaveActivatedAbility('Ability.Slot.Q', { times: 1 });
// Assert no rapid-fire duplicate warnings occurred
expect(warnings).toHaveLength(0);
});Causality Timeline Integration
If an assertion fails later in the test (for instance, an enemy takes more damage than expected), the Watchdog warnings are automatically surfaced in theGAS Event Causality Timeline with the ⚠️ [DIAGNOSTIC WARNING] marker, pinpointing the exact timing and culprit immediately.