# Factory System Overview

The **Factory System** defines how the Runtime Spawner creates, reuses, and destroys game objects.\
It abstracts *the method of instantiation* (local, pooled, or networked) from *the logic of spawning*, allowing the same spawner setup to function across both single-player and multiplayer contexts.

Factories are configured through **ScriptableObject assets** derived from `ObjectFactoryAsset`.\
At runtime, these assets produce a concrete `IObjectFactory` instance that the spawner uses internally.

***

### 1. Concept

When the Runtime Spawner performs a spawn, it doesn’t call `Instantiate()` directly - instead, it delegates the task to its assigned **Object Factory**.

```csharp
// inside SpawnExecutor
activeFactory.Spawn(entry, position, rotation);
```

This approach lets you swap the underlying creation logic -\
for example, from a simple pooled spawn in single-player to a networked spawn in Fusion or PUN - without altering any scene or wave configuration.

***

### 2. Base Class: `ObjectFactoryAsset`

All runtime factories derive from the abstract `ObjectFactoryAsset` base class.

```csharp
public abstract class ObjectFactoryAsset : ScriptableObject
{
    public abstract IObjectFactory Create();
}
```

At runtime, the `RuntimeSpawner` calls `factoryAsset.Create()` to obtain the active `IObjectFactory` implementation.\
This instance handles all spawn/despawn requests for the duration of the session.

Each subclass defines how and where instances are created - for example, in local memory or over the network.

***

### 3. Built-In Factory Assets

<table><thead><tr><th width="257.5333251953125">Factory Asset</th><th>Runtime Implementation</th><th>Use Case</th></tr></thead><tbody><tr><td><strong>SinglePlayerPoolFactoryAsset</strong></td><td><code>SinglePlayerPoolFactory</code></td><td>Local or offline gameplay using pooled instantiation</td></tr><tr><td><strong>FusionFactoryAsset</strong></td><td><code>FusionObjectFactory</code></td><td>Photon Fusion 2.x multiplayer</td></tr><tr><td><strong>PUNFactoryAsset</strong></td><td><code>PUNObjectFactory</code></td><td>Photon PUN 2+ multiplayer</td></tr></tbody></table>

All assets are created from the Unity menu:

```
Create → Megacrush → Spawner → Factories → [Factory Type]
```

Assign one of these assets to the **Factory** field of your `RuntimeSpawner`.

***

### 4. Example: Single-Player Pool Factory

```csharp
using UnityEngine;

namespace MegaCrush.Spawner
{
    /// <summary>
    /// ScriptableObject factory asset that creates a <see cref="SinglePlayerPoolFactory"/> instance.
    /// </summary>
    [CreateAssetMenu(menuName = EditorMenuPaths.Factories + "Single Player Pool Factory")]
    public sealed class SinglePlayerPoolFactoryAsset : ObjectFactoryAsset
    {
        public override IObjectFactory Create()
        {
            // Uses the shared PoolAdapter from the Object Pool package.
            return new SinglePlayerPoolFactory(new PoolAdapter());
        }
    }
}
```

#### Description

* Provides local instantiation and despawning through the **Object Pool** package.
* Ideal for single-player, offline, or editor testing contexts.
* Implements efficient reuse via `PoolAdapter` to minimize allocations.

#### Recommended Setup

* Assign to any Runtime Spawner in single-player projects.
* Works seamlessly with the **Spawn Hint**, **Region**, and **Wave** systems.
* Requires the **Megacrush Object Pool** package (installed automatically).

***

### 5. Example: Photon Fusion Factory

```csharp
[CreateAssetMenu(menuName = EditorMenuPaths.Factories + "Photon Fusion Factory")]
public sealed class FusionFactoryAsset : ObjectFactoryAsset
{
    public override IObjectFactory Create()
    {
        return new FusionObjectFactory();
    }
}
```

#### Description

* Produces a `FusionObjectFactory` that integrates with **Photon Fusion 2.x**.
* Spawns objects via `NetworkRunner.Spawn()` and manages reuse through `FusionPoolObjectProvider`.
* Automatically synchronized across clients; only the Host/Server spawns.

#### Notes

* Requires a `NetworkRunner` configured with `FusionPoolObjectProvider`.
* Works with the provided **Fusion Bootstrap Sample Scene**.
* Fully supports the Runtime Spawner lifecycle (`Init`, `Pause`, `End`).

***

### 6. Example: Photon PUN 2+ Factory

```csharp
[CreateAssetMenu(menuName = EditorMenuPaths.Factories + "Photon PUN 2+ Factory")]
public sealed class PUNFactoryAsset : ObjectFactoryAsset
{
    public override IObjectFactory Create()
    {
        return new PUNObjectFactory();
    }
}
```

#### Description

* Integrates the spawner with **Photon PUN 2+** using `PhotonNetwork.Instantiate()`.
* Works with `PUNPoolPrefabProvider` for pooled instantiation.
* The **Master Client** runs the spawner; other clients receive updates automatically.

#### Notes

* Supports automatic prefab registration through `PUNPrefabRegistrar`.
* Tested with the included **PUN Sample Scene**.
* Handles master transfer gracefully - the new master automatically restarts spawner flow.

***

### 7. Custom Factory Assets

You can extend the system by deriving your own `ObjectFactoryAsset`.\
For example, to support **Addressables** or a **custom pooling backend**:

```csharp
[CreateAssetMenu(menuName = EditorMenuPaths.Factories + "Addressable Factory")]
public sealed class AddressableFactoryAsset : ObjectFactoryAsset
{
    public override IObjectFactory Create()
    {
        return new AddressableFactory();
    }
}
```

Your corresponding runtime implementation might look like:

```csharp
public class AddressableFactory : IObjectFactory
{
    public async Task<GameObject> Spawn(SpawnEntry entry, Vector3 pos, Quaternion rot)
    {
        var handle = Addressables.InstantiateAsync(entry.prefabRef, pos, rot);
        return await handle.Task;
    }

    public void Despawn(GameObject instance)
    {
        Addressables.ReleaseInstance(instance);
    }
}
```

#### Guidelines

* Keep factories stateless; create transient runtime instances from assets.
* If using asynchronous creation (like Addressables), integrate with deferred spawn logic.
* You can attach a custom `IPoolAdapter` or `IObjectProvider` for advanced reuse.

***

### 8. Lifecycle Integration

All factories follow the spawner lifecycle automatically.

| Spawner Call           | Factory Behavior                                                 |
| ---------------------- | ---------------------------------------------------------------- |
| `Init()`               | Factory initializes internal pools or providers.                 |
| `Pause()` / `Resume()` | Temporarily halts or resumes spawn execution.                    |
| `End()`                | Cleanly despawns all active instances and disposes of providers. |

When you transition between game states (e.g., mission start/end, network join/leave), the factory’s lifecycle methods are automatically invoked in sync with the spawner.

***

### 9. Debugging & Diagnostics

Enable **Verbose Logs** in the `RuntimeSpawner` inspector or through the **Spawner Diagnostics HUD** to trace which factory is being used at runtime.

Example log output:

```
[RuntimeSpawner] Using FusionFactoryAsset (networked mode)
[FusionObjectFactory] Spawned Enemy_Trooper (NetworkID 34)
[ObjectPool] Returned Enemy_Trooper to pool (active=12)
```

You can also confirm correct lifecycle operation via logs like:

```
[RuntimeSpawner] Factory.End() called – released 42 instances.
```

***

### 10. Choosing a Factory

| Scenario                         | Recommended Factory                     |
| -------------------------------- | --------------------------------------- |
| Offline / local game             | **SinglePlayerPoolFactoryAsset**        |
| Deterministic co-op using Fusion | **FusionFactoryAsset**                  |
| Lightweight peer-to-peer         | **PUNFactoryAsset**                     |
| Cloud / streaming / ECS / custom | Custom subclass of `ObjectFactoryAsset` |

Switching is as simple as assigning a different asset in the inspector.

```csharp
spawner.Factory = myFactoryAsset;
```

At runtime, the spawner will automatically instantiate the correct factory via `factoryAsset.Create()`.

***

### ✅ Summary

The Factory System provides a unified abstraction for all spawn and despawn behavior:

* **Editor-friendly configuration** via ScriptableObject assets
* **Flexible runtime backend** (local pool, Fusion, PUN, custom)
* **Consistent lifecycle integration** with pause, resume, and end states
* **Zero scene changes** required when switching between modes

> **In short:** Factories define *how* your world spawns -\
> while the Runtime Spawner continues to define *what* and *when*.
