Telemetry Providers - Samples & Patterns
Special Encounter Manager Telemetry samples
Telemetry Provider (Optional)
Why it matters Rules can require Pressure or Average Player HP values. These are game-specific and cannot be hardcoded. The manager queries a Telemetry Provider at runtime:
If available → values are compared against rule thresholds.
If missing → the condition automatically fails (safe default, no spawn).
Supplying Telemetry
ScriptableObject Provider (Inspector)
Base:
SpecialsTelemetryProvider
(abstract).Sample:
BasicSpecialsTelemetry
(inSamples~
) – lets you enter static test values.Workflow:
Create via Assets → Create → MegaCrush → Spawner → Specials Telemetry.
Assign to Telemetry Provider field.
Code Provider (ISpecialsTelemetry)
Implement the
ISpecialsTelemetry
interface in your game system (e.g. GameState, DifficultyManager).Inject at runtime:
encounterManager.SetTelemetryProvider(myCustomProvider);
Telemetry Hooks
Pressure (float, any scale: 0–1 recommended).
e.g.
currentEnemies / maxEnemies
e.g. director intensity level
Average Player HP (float 0–1).
e.g. sum of all players’ health% / player count
System Flow (Telemetry Evaluation)
┌───────────────────────────────┐
│ SpecialEncounterManager │
│ (runs each eval interval) │
└───────────────┬───────────────┘
│
▼
┌─────────────────────┐
│ Special Rule(s) │
│ - Step Range │
│ - Alive Cap │
│ - Cooldowns │
│ - Telemetry Gates? │
└─────────┬───────────┘
│
Needs Pressure / Avg HP?
│
┌──────┴────────┐
▼ ▼
┌────────────────┐ ┌─────────────────┐
│ Telemetry │ │ No Provider Set │
│ Provider │ │ (rule fails │
│ (SO or code) │ │ quietly, no │
│ │ │ spawn occurs) │
└───────┬────────┘ └─────────────────┘
│
▼
┌──────────────────────────────┐
│ Values returned (Pressure, │
│ Avg Player HP, etc) │
└───────────┬──────────────────┘
│
Compare vs thresholds
│
▼
┌─────────────────────────────┐
│ Rule passes → spawn agent │
│ Rule fails → no spawn │
└─────────────────────────────┘
BasicSpecialsTelemetry (included in Samples)
Purpose
BasicSpecialsTelemetry
is a minimal ScriptableObject provider you can use to test Special Encounter rules without wiring any real game systems. It exposes two sliders—Pressure and Average Player HP—that the SpecialEncounterManager
will read during rule evaluation.
// Samples~/.../BasicSpecialsTelemetry.cs
using UnityEngine;
namespace MegaCrush.Spawner.Samples
{
[CreateAssetMenu(menuName = "Runtime Spawner/Specials Telemetry/Basic Sample")]
public sealed class BasicSpecialsTelemetry : SpecialsTelemetryProvider
{
[Range(0f, 1f)] public float pressure = 0f;
[Range(0f, 1f)] public float averagePlayerHP = 1f;
public override bool TryGetPressure(out float value) { value = pressure; return true; }
public override bool TryGetAveragePlayerHP(out float value) { value = averagePlayerHP; return true; }
}
}
When to use it
You’re validating Special Rules (thresholds, cooldowns, step ranges) before your gameplay systems are ready.
You want to see how changing Pressure or Avg HP impacts encounter timing in real time.
You’re building automated tests around rules that need deterministic values.
Create & Assign (Quickstart)
Create the asset
Assets → Create → Runtime Spawner → Specials Telemetry → Basic Sample
Assign it on the Manager In the Special Encounter Manager inspector, set Telemetry Provider to your new
BasicSpecialsTelemetry
asset.Play Mode Tweak the Pressure and Average Player HP sliders on the asset while the game runs and observe:
Rule pass/fail based on thresholds
Spawn frequency and tags
“Runtime Status” in the Manager inspector (Next/Last spawn times)
What the sliders mean
Pressure: Any scalar you choose (commonly 0–1). Higher = more stress/intensity.
Average Player HP: Mean health across players (0–1). Lower = team is hurt.
Note: Rule checks read these values via the provider on each evaluation. If a rule requires telemetry and no provider is assigned, that condition fails safely (no spawn).
Extending Beyond the Sample
Base Class: SpecialsTelemetryProvider
SpecialsTelemetryProvider
Use this when you want an inspector-driven provider (SO asset) that pulls values from your game.
public abstract class SpecialsTelemetryProvider : ScriptableObject, ISpecialsTelemetry
{
public abstract bool TryGetPressure(out float value);
public abstract bool TryGetAveragePlayerHP(out float value);
}
Pattern: SO provider that reads from your systems
using UnityEngine;
public sealed class GameLinkedTelemetry : SpecialsTelemetryProvider
{
public override bool TryGetPressure(out float value)
{
// Example: read from a singleton/service
value = MyGame.Difficulty.CurrentPressure01;
return true;
}
public override bool TryGetAveragePlayerHP(out float value)
{
value = MyGame.Players.AverageHealth01;
return true;
}
}
Pros
Easy to swap per scene/profile.
Editable references in the inspector.
Works with addressables/asset workflows.
Cons
Slightly more setup than a pure code approach.
Interface: ISpecialsTelemetry
ISpecialsTelemetry
Use this when you want to inject a pure code provider at runtime.
public interface ISpecialsTelemetry
{
bool TryGetPressure(out float value);
bool TryGetAveragePlayerHP(out float value);
}
Pattern: Code provider injected at runtime
public sealed class RuntimeTelemetry : ISpecialsTelemetry
{
private readonly DifficultyManager _dm;
private readonly PlayerService _players;
public RuntimeTelemetry(DifficultyManager dm, PlayerService players)
{ _dm = dm; _players = players; }
public bool TryGetPressure(out float value)
{
value = _dm.Pressure01;
return true;
}
public bool TryGetAveragePlayerHP(out float value)
{
value = _players.GetAverageHealth01();
return true;
}
}
// Injection
var mgr = FindObjectOfType<SpecialEncounterManager>();
mgr.SetTelemetryProvider(new RuntimeTelemetry(difficulty, players));
Pros
No assets required.
Easy to unit test.
Perfect for service/DI architectures.
Cons
Not directly swappable via inspector.
Choosing a Scale
Recommended: Normalize to 0–1 for both Pressure and Avg HP so thresholds are easy to reason about.
If you use a different scale, keep it consistent across rules and providers.
Common Rule Examples (With Telemetry)
Miniboss under pressure
Min Pressure ≥ 0.75
,Step Range 3–99
,Cooldown 180s
Flankers only when team is healthy
Min Avg HP ≥ 0.6
,Require No LOS = true
,Distance 18–32m
Snipers when players are low
Use reverse gate by creating two variants:
Rule A (sniper):
Min Pressure ≥ 0.5
,Min Avg HP ≥ 0.3
Baseline population reduces to make room (via director/other rules)
Troubleshooting
Nothing spawns despite rules valid
Check Max Simultaneous Specials and Min Gap Seconds on the Profile.
Ensure alive cap for the rule isn’t already reached.
Verify Step Range matches the Director’s current step.
Confirm Telemetry Provider is assigned (or injected) if the rule uses telemetry.
Require No LOS never passes
Set Occluder Mask to include geometry layers that should block line‑of‑sight.
Verify anchors are placed behind occluders relative to the player.
Provider values aren’t changing
If using an SO provider, you can tweak asset fields at runtime.
If using a code provider, ensure you call
SetTelemetryProvider(...)
after your systems are initialized and that your getters return updated values each frame.
Quick Checklist
Create a Special Profile, add rules with telemetry thresholds.
Assign BasicSpecialsTelemetry to the Manager to validate behavior.
Replace the sample with a Game‑linked SO provider or code provider implementing
ISpecialsTelemetry
.Use the Manager’s Runtime Status and Force Roll Now to iterate quickly.
Last updated