# Using the Runtime Spawner Fusion Pool Provider

## **Runtime Spawner – Fusion Pool Provider Integration**

#### **How Fusion + Runtime Spawner Pooling Works**

Runtime Spawner ships with a **FusionPoolObjectProvider**, a component that plugs directly into Fusion’s `INetworkObjectProvider` API.

This component **must** be the runner’s provider when using Runtime Spawner in Fusion mode.

Because Fusion only supports **one** provider per runner:

* If you previously used Fusion’s `NetworkObjectProviderDefault`
* Or your own custom provider\
  → Runtime Spawner’s provider replaces it on that runner.

Runtime Spawner now owns pooling, Fusion still owns networking and authority replication.

***

## **What Runtime Spawner’s Fusion Pool Provider Does**

With `FusionPoolObjectProvider` added to your `NetworkRunner`:

#### **Fusion**

* Calls `AcquirePrefabInstance()` when it needs a new instance
* Calls `ReleaseInstance()` when despawning a network object

#### **Runtime Spawner**

* Provides the instance from its internal pool
* Prewarms pools from SpawnEntries
* Tracks per-entry + global population caps
* Ensures proper enable/disable lifecycle for pooled instances
* Ensures networked despawn goes through Fusion first but still returns to Runtime Spawner's pool

**Fusion owns the network lifecycle.**\
**Runtime Spawner owns the object pooling.**

***

## **How to Spawn and Despawn Objects**

This is the #1 point users get stuck on, so here is the definitive guidance.

***

### **How Spawning Works**

#### **Automatic spawning**

If you’re using:

* Global spawners
* Region spawners
* Wave spawners

… then spawning is **fully automatic.**\
You do **not** manually call `Runner.Spawn()`.

Runtime Spawner internally drives spawning through its factory abstraction, and the Fusion pool provider ensures that:

* Fusion sees the spawned object
* The pooled instance is reused
* Networking replication happens correctly

Users do not need to write any spawn code unless doing custom spawns.

***

#### **Manual spawning (advanced / optional)**

If your game needs to manually spawn something (e.g., player abilities, projectiles), you must go through **Runtime Spawner’s factory**, not Fusion directly.

Use:

```csharp
var instance = RuntimeSpawner.Instance.Executor.Spawn(entry, context);
```

But since this is advanced, typical users do not need this.

***

## **How to Despawn Objects**

This is the most important part for Fusion users.

There are **three correct ways** to despawn something:

***

### **1. Automatic Despawn (waves, culling, region exit)**

Runtime Spawner will:

* Detect the despawn condition
* Look up the `ISpawnHandle` associated with the instance
* Call `Runner.Despawn()` (if networked)
* Return the object to the pool
* Update internal population bookkeeping

You don’t need to do anything.

***

### **2. Call `RuntimeSpawner.Despawn(GameObject)`**

This is the recommended API for gameplay scripts.

```csharp
RuntimeSpawner.Despawn(gameObject);
```

This method:

* Looks up the owning RuntimeSpawner
* Checks if the object has a Fusion `ISpawnHandle`
* If networked → calls `handle.Despawn()` → Fusion replicates despawn
* If not → returns the object to the pool
* Updates all internal population and SpawnEntry counts

**This is the safest despawn method for Fusion + pooling.**

***

### **3. Call `ISpawnHandle.Despawn()` yourself (advanced)**

If you cached the handle from the factory you may call that directly.

Gamers rarely need to do this unless writing custom spawn flows.

***

## **Should I Call Runner.Despawn Myself?**

#### **Short answer: NO — not when using Runtime Spawner.**

Fusion’s `Runner.Despawn(obj)` will only:

* Replicate destruction across network clients
* Release the instance back to the **Fusion** pooling system (which Runtime Spawner has replaced)

But it will **not update**:

* SpawnEntry population
* Global population
* Internal bookkeeping
* Owner maps
* SpawnedObject list
* Region/wave counts

This breaks spawn balancing.

#### **Correct Pattern**

Instead of:

```csharp
Runner.Despawn(gameObject);
```

Use:

```csharp
RuntimeSpawner.Despawn(gameObject);
```

This ensures:

✔ Fusion replication\
✔ Returned to Runtime Spawner's pool\
✔ Correct population tracking\
✔ Wave/region/global systems stay consistent

***

## **Prefab-Level Lifecycle: OnEnable / OnDisable**

If your old pooling system used OnSpawned/OnDespawned, convert it to:

```csharp
void OnEnable() { /* init */ }
void OnDisable() { /* cleanup */ }
```

Runtime Spawner guarantees:

* Pooled objects are disabled when returned
* Enabled when spawned
* Re-enable calls happen for reused objects
* Works safely in Fusion scenes

Recommended uses:

* Reset health
* Reset behavior state
* Play VFX/SFX
* Re-register with AI managers
* Start movement/pathfinding logic

***

## **Global Hooks for Analytics / Manager Systems**

You can listen to spawn/despawn events:

```csharp
RuntimeSpawner.onObjectSpawned += obj => { ... };
RuntimeSpawner.onObjectCulled += obj => { ... };
RuntimeSpawner.onUpdateCurrentPopulation += count => { ... };
```

This replaces custom provider logic you may have had before.

***

## **Advanced: Wrapping the Fusion Provider**

If your project used custom routing in your old provider, you can wrap the Runtime Spawner provider:

```csharp
public class MyWrappedFusionProvider : MonoBehaviour, INetworkObjectProvider
{
    public FusionPoolObjectProvider rspProvider;

    public NetworkObjectAcquireResult AcquirePrefabInstance(...) {
        // pre logic
        return rspProvider.AcquirePrefabInstance(...);
    }

    public bool ReleaseInstance(...) {
        // post logic
        return rspProvider.ReleaseInstance(...);
    }
}
```

This is rarely needed but fully supported.

***

## **Migration Checklist (Updated)**

#### **When migrating from Fusion’s default pooling to Runtime Spawner:**

**Required**

✔ Remove existing `INetworkObjectProvider` from the runner\
✔ Add `FusionPoolObjectProvider` (or your wrapper)\
✔ Ensure Runtime Spawner uses the Fusion factory mode

**Prefab updates**

✔ Move OnSpawned/OnDespawned logic → OnEnable/OnDisable\
✔ Ensure your NPCs/AI reset correctly when reused

**Gameplay scripts**

Replace:

```csharp
Runner.Despawn(gameObject);
```

With:

```csharp
RuntimeSpawner.Despawn(gameObject);
```

**Global systems**

✔ If you track active enemies/objects → subscribe to Runtime Spawner events

**Optional**

✔ For manual spawns → use Runtime Spawner’s executor, not Fusion directly

***

## **Final Summary**&#x20;

#### **How do I despawn an object?**

```csharp
RuntimeSpawner.Despawn(gameObject);
```

#### **Should I use Runner.Despawn?**

**No.** Runtime Spawner must route the despawn so it can:

* Update SpawnEntry population
* Update global population
* Remove bookkeeping
* Return to the internal pool
* Trigger Fusion’s network replication (if networked)

#### **How do I spawn new enemies manually?**

Typically you don’t.\
Spawning is handled by global, region, or wave systems.\
If you must, use RuntimeSpawner’s executor.

#### **What events can I listen to?**

* `RuntimeSpawner.onObjectSpawned`
* `RuntimeSpawner.onObjectCulled`
* `RuntimeSpawner.onUpdateCurrentPopulation`
* etc.
