> For the complete documentation index, see [llms.txt](https://megacrush.gitbook.io/megacrush-unity-assets/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://megacrush.gitbook.io/megacrush-unity-assets/runtime-spawner/runtime-spawner-user-manual/getting-started/specials-telemetry-system/creating-a-custom-telemetry-provider.md).

# Creating a Custom Telemetry Provider

Once you’ve confirmed your **Special Encounter rules** respond correctly using the sample asset, you can connect your **real gameplay data** by creating your own telemetry provider.

The telemetry system is intentionally flexible - you can feed in *any data source* as long as it provides two values:

| Metric                | Description                                     | Typical Range    |
| --------------------- | ----------------------------------------------- | ---------------- |
| **Pressure**          | How intense or “busy” the game currently feels. | 0–1 (normalized) |
| **Average Player HP** | The team’s mean health percentage.              | 0–1 (normalized) |

There are two main ways to implement a provider:

an **Inspector-based ScriptableObject** (plug-and-play) or a **runtime C# provider** (for live data).

***

### Option A - ScriptableObject Provider (Inspector Setup)

Use this approach when you want a configurable, reusable asset that can read or proxy values from your systems.

#### 1. Create a subclass of `SpecialsTelemetryProvider`

```csharp
using UnityEngine;
using MegaCrush.Spawner;

[CreateAssetMenu(menuName = "Runtime Spawner/Specials Telemetry/Game Linked")]
public sealed class GameLinkedTelemetry : SpecialsTelemetryProvider
{
    public override bool TryGetPressure(out float value)
    {
        // Example: pull from your own difficulty or director service
        value = GameServices.Difficulty.CurrentPressure01;
        return true;
    }

    public override bool TryGetAveragePlayerHP(out float value)
    {
        value = GameServices.Players.GetAverageHealth01();
        return true;
    }
}
```

#### 2. Create the asset

In Unity:\
**Create → Runtime Spawner → Specials Telemetry → Game Linked**

#### 3. Assign it to the Manager

Select your **SpecialEncounterManager** and drag your new asset into the **Telemetry Provider** field.

That’s it - your manager will now query your game’s live values automatically every evaluation cycle.

***

#### Pros

* Editable and swappable via inspector or profiles.
* Works with Addressables or asset-based pipelines.
* Ideal for designers tuning different pacing profiles.

#### Cons

* Slightly more setup than a code-only provider.
* Requires script access to your global systems or singletons.

***

### Option B - Runtime Provider (Code Injection)

If your telemetry data already lives in runtime systems (e.g., `GameState`, `DifficultyManager`, `PlayerService`), you can implement the lightweight **ISpecialsTelemetry** interface and inject it directly.

#### 1. Implement the interface

```csharp
using MegaCrush.Spawner;

public sealed class RuntimeTelemetry : ISpecialsTelemetry
{
    private readonly DifficultyManager _difficulty;
    private readonly PlayerService _players;

    public RuntimeTelemetry(DifficultyManager difficulty, PlayerService players)
    {
        _difficulty = difficulty;
        _players = players;
    }

    public bool TryGetPressure(out float value)
    {
        value = _difficulty.PressureNormalized;  // 0..1
        return true;
    }

    public bool TryGetAveragePlayerHP(out float value)
    {
        value = _players.GetAverageHealth01();
        return true;
    }
}
```

#### 2. Inject it at runtime

```csharp
var manager = FindAnyObjectByType<SpecialEncounterManager>();
manager.SetTelemetryProvider(new RuntimeTelemetry(difficulty, players));
```

You can inject it right after initializing the Runtime Spawner or during your bootstrap sequence.

***

#### Pros

* No asset setup required.
* Works cleanly with dependency injection and services.
* Easy to test and mock.

#### Cons

* Not visible in the inspector.
* Requires code changes if you want to swap providers.

***

### Recommended Scales

Keep telemetry values **normalized between 0 and 1**.\
This keeps thresholds predictable across different rule sets:

| Value | Interpretation                           |
| ----- | ---------------------------------------- |
| 0.0   | Calm / no intensity / players near death |
| 0.5   | Normal tension / moderate health         |
| 1.0   | Extreme intensity / full health          |

Rules like

> *“Spawn a miniboss when Pressure ≥ 0.8 and AvgHP ≥ 0.5”*\
> will be easier to tune when all systems use a consistent scale.

***

### Advanced: Combining Providers

You can dynamically swap telemetry sources:

```csharp
// During a cutscene or transition
manager.SetTelemetryProvider(new NullTelemetry());  // disables telemetry temporarily
// Later
manager.SetTelemetryProvider(liveTelemetry);        // re-enable live data
```

Any call to `SetTelemetryProvider()` overrides the inspector field until the next scene load or reinitialization.

***

### Summary

| Goal                               | Recommended Provider                                     |
| ---------------------------------- | -------------------------------------------------------- |
| Quick iteration in editor          | **BasicSpecialsTelemetry** sample                        |
| Connect to real data (asset-based) | Subclass **SpecialsTelemetryProvider**                   |
| Integrate live runtime data        | Implement **ISpecialsTelemetry** and inject at runtime   |
| Switch dynamically                 | Use `SetTelemetryProvider()` between different providers |

> **Tip:**\
> For most projects, start with a ScriptableObject subclass for clarity,\
> then move to a runtime provider once your gameplay systems are stable.

***

**In short:**\
Custom telemetry gives your **Special Encounter Manager** true awareness of your game’s pacing - so your boss waves, ambushes, or rare encounters appear exactly when the tension and player condition are right.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://megacrush.gitbook.io/megacrush-unity-assets/runtime-spawner/runtime-spawner-user-manual/getting-started/specials-telemetry-system/creating-a-custom-telemetry-provider.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
