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

  1. ScriptableObject Provider (Inspector)

    • Base: SpecialsTelemetryProvider (abstract).

    • Sample: BasicSpecialsTelemetry (in Samples~) – lets you enter static test values.

    • Workflow:

      • Create via Assets → Create → MegaCrush → Spawner → Specials Telemetry.

      • Assign to Telemetry Provider field.

  2. 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)

  1. Create the asset Assets → Create → Runtime Spawner → Specials Telemetry → Basic Sample

  2. Assign it on the Manager In the Special Encounter Manager inspector, set Telemetry Provider to your new BasicSpecialsTelemetry asset.

  3. 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

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

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

  1. Create a Special Profile, add rules with telemetry thresholds.

  2. Assign BasicSpecialsTelemetry to the Manager to validate behavior.

  3. Replace the sample with a Game‑linked SO provider or code provider implementing ISpecialsTelemetry.

  4. Use the Manager’s Runtime Status and Force Roll Now to iterate quickly.

Last updated