How to: Using Specials Telemetry
Prerequisites
Runtime Spawner is in your scene and calls
Init(...)
→Begin()
on startup.A
SpecialEncounterManager
is present and assigned aSpecialProfile
with at least oneSpecialRule
.Your project has TextMeshPro and the Diagnostics HUD in the scene (or you’ve added it).
1) Choose how you’ll provide telemetry
You can feed “Pressure” and “Average Player HP” into specials via either:
Option A (Inspector / ScriptableObject): subclass
SpecialsTelemetryProvider
and assign the asset on the manager.Option B (Code / Interface): implement
ISpecialsTelemetry
and inject the instance at runtime.
Both options can coexist; if you call SetTelemetryProvider(...)
at runtime, that overrides the SO field.
2) Option A — ScriptableObject provider (Inspector setup)
Create a provider asset:
Right‑click in Project: Create → MegaCrush → Spawner → Specials Telemetry (use your subclass or the
BasicSpecialsTelemetry
sample underSamples~
for testing).
Assign it:
Select your
SpecialEncounterManager
in the scene.Drag the provider asset into the Telemetry Provider field.
Hook your real data (recommended):
In your subclass of
SpecialsTelemetryProvider
, implement:public override bool TryGetPressure(out float value) { /* set value */ } public override bool TryGetAveragePlayerHP(out float value) { /* set value */ }
Pull values from your game systems (difficulty/AI director, health system, etc.).
Notes:
The sample asset exposes static sliders—useful to prove the pipeline works, then replace with a real subclass.
3) Option B — Code provider (runtime injection)
Implement the interface anywhere in your game:
using MegaCrush.Spawner; public sealed class MyTelemetry : ISpecialsTelemetry { public bool TryGetPressure(out float value) { // Example: normalized by your max enemy budget value = CurrentEnemyCount / (float)MaxEnemyBudget; return true; } public bool TryGetAveragePlayerHP(out float value) { // Example: average over all active players (0..1) value = ComputeAveragePlayerHealthNormalized(); return true; } }
Inject it before specials begin:
// wherever you bootstrap spawner systems after SpecialEncounterManager.Init(...) var specials = FindAnyObjectByType<SpecialEncounterManager>(); specials.SetTelemetryProvider(new MyTelemetry());
4) Configure rules that use telemetry
Open your SpecialProfile
and for any SpecialRule
you want gated:
Set minPressure to a threshold (e.g.,
0.75
).Set minAvgPlayerHP (0..1) if you want to avoid spawning when players are very low.
Ensure stepRange, maxAlive, evalEverySeconds, cooldownSeconds, distanceRange, and spawnTag are configured sensibly.
Behavior:
If a rule requires telemetry but no provider is available, the rule’s condition fails (special won’t spawn). Everything else continues to work.
5) Enable the Diagnostics HUD timing (optional but recommended)
If you’ve updated the HUD with the added fields:
Assign in the HUD inspector:
SpecialsTimerText
SpecialsLastSpawnText
SpecialsNextTagText
In play mode, you’ll see:
“Specials: next in Xs (at Y.s)” — the next evaluation ETA.
“Last special: Ns ago” — last successful special time.
“Next Tag: …” — the planned tag (best effort debug hint).
The Population section’s Total Active shows the live count, and the per‑source breakdown helps confirm sources (Global/Region/Wave/Special).
6) Quick test workflow
Put your player into the scene and ensure
RuntimeSpawner
knows the PlayerTransform.Use the sample
BasicSpecialsTelemetry
asset (Option A) and set:pressure = 0.9
averagePlayerHP = 1.0
In your
SpecialProfile
, set one rule with:minPressure = 0.8
minAvgPlayerHP = 0.5
Reasonable
evalEverySeconds
(e.g., 1–3s) andcooldownSeconds
(e.g., 10–20s).
Enter Play:
Watch the HUD: ETA should count down; last spawn updates when a special appears.
If you’re step‑gated, advance your Director step and verify the HUD updates “Intensity Step”.
Tip (Editor only): you can use the context menu Force Specials Roll Now on SpecialEncounterManager
to arm all rules immediately. This is wrapped in #if UNITY_EDITOR
and excluded from builds.
7) Troubleshooting
“Specials: (unscheduled)” Likely all rules are ineligible (step gating, no rules, or evaluation times in the future). Advance the Director step or reduce thresholds.
No spawns despite positive thresholds Check:
minGapSeconds
on the profile (global cooldown).maxAlive
for the rule (you may be at cap).Anchor availability: ensure
WaveSpawnPoint
s exist with matchingspawnTag
, correctdistanceRange
, and LOS setting (ifrequireNoLOS
, confirm an occluder actually blocks).Telemetry provider returns
true
and supplies values that meet thresholds.
HUD “Total Active” climbs forever Ensure you’re on the updated HUD that uses
_pop.Current
for the live count.Nothing happens after scene load Confirm your flow calls:
RuntimeSpawner.Init(...)
→SpecialEncounterManager.Init(...)
(done by spawner) →RuntimeSpawner.StartSpawners()
→SpecialEncounterManager.Begin()
(called by spawner).
Last updated