Table of Contents

Class ObjectSpawner

Namespace
FishMMO.Shared
Assembly
FishMMO.Shared.dll

Manages spawning and respawning of networked objects in the game world. Supports various spawn types, respawn conditions, and object pooling.

[RequireComponent(typeof(NetworkObject))]
public class ObjectSpawner : NetworkBehaviour
Inheritance
Object
Component
Behaviour
MonoBehaviour
NetworkBehaviour
ObjectSpawner
Inherited Members
NetworkBehaviour.IsSpawned
NetworkBehaviour.ComponentIndex
NetworkBehaviour.NetworkObject
NetworkBehaviour.MAXIMUM_NETWORKBEHAVIOURS
NetworkBehaviour.UNSET_NETWORKBEHAVIOUR_ID
NetworkBehaviour.ToString()
NetworkBehaviour.Reset()
NetworkBehaviour.OnValidate()
NetworkBehaviour.IsBehaviourReconciling
NetworkBehaviour.ClearReplicateCache()
NetworkBehaviour.CreateReconcile()
NetworkBehaviour.Reconcile_Reader<T>(PooledReader, ref T)
NetworkBehaviour.OnStartServerCalled
NetworkBehaviour.OnStartClientCalled
NetworkBehaviour.WritePayload(NetworkConnection, Writer)
NetworkBehaviour.ReadPayload(NetworkConnection, Reader)
NetworkBehaviour.OnStartServer()
NetworkBehaviour.OnStopServer()
NetworkBehaviour.OnOwnershipServer(NetworkConnection)
NetworkBehaviour.OnSpawnServer(NetworkConnection)
NetworkBehaviour.OnDespawnServer(NetworkConnection)
NetworkBehaviour.OnStartClient()
NetworkBehaviour.OnStopClient()
NetworkBehaviour.OnOwnershipClient(NetworkConnection)
NetworkBehaviour.ClearBuffedRpcs()
NetworkBehaviour.ExcludeOwnerFromUnbufferedObserversRpcs
NetworkBehaviour.IsClientOnly
NetworkBehaviour.IsServerOnly
NetworkBehaviour.IsHost
NetworkBehaviour.IsClient
NetworkBehaviour.IsServer
NetworkBehaviour.IsDeinitializing
NetworkBehaviour.NetworkManager
NetworkBehaviour.ServerManager
NetworkBehaviour.ClientManager
NetworkBehaviour.ObserverManager
NetworkBehaviour.TransportManager
NetworkBehaviour.TimeManager
NetworkBehaviour.SceneManager
NetworkBehaviour.PredictionManager
NetworkBehaviour.RollbackManager
NetworkBehaviour.NetworkObserver
NetworkBehaviour.IsClientInitialized
NetworkBehaviour.IsClientStarted
NetworkBehaviour.IsClientOnlyInitialized
NetworkBehaviour.IsClientOnlyStarted
NetworkBehaviour.IsServerInitialized
NetworkBehaviour.IsServerStarted
NetworkBehaviour.IsServerOnlyInitialized
NetworkBehaviour.IsServerOnlyStarted
NetworkBehaviour.IsHostInitialized
NetworkBehaviour.IsHostStarted
NetworkBehaviour.IsOffline
NetworkBehaviour.IsNetworked
NetworkBehaviour.GetIsNetworked()
NetworkBehaviour.IsManagerReconciling
NetworkBehaviour.Observers
NetworkBehaviour.IsOwner
NetworkBehaviour.IsController
NetworkBehaviour.HasAuthority
NetworkBehaviour.Owner
NetworkBehaviour.OwnerId
NetworkBehaviour.ObjectId
NetworkBehaviour.LocalConnection
NetworkBehaviour.OwnerMatches(NetworkConnection)
NetworkBehaviour.Despawn(GameObject, DespawnType?)
NetworkBehaviour.Despawn(NetworkObject, DespawnType?)
NetworkBehaviour.Despawn(DespawnType?)
NetworkBehaviour.Spawn(GameObject, NetworkConnection, Scene)
NetworkBehaviour.Spawn(NetworkObject, NetworkConnection, Scene)
NetworkBehaviour.RemoveOwnership()
NetworkBehaviour.GiveOwnership(NetworkConnection)
NetworkBehaviour.GetInstance<T>()
NetworkBehaviour.TryRegisterInstance<T>(T)
NetworkBehaviour.UnregisterInstance<T>()
NetworkBehaviour.CanLog(LoggingType)
MonoBehaviour.IsInvoking()
MonoBehaviour.CancelInvoke()
MonoBehaviour.StopCoroutine(Coroutine)
MonoBehaviour.StopAllCoroutines()
MonoBehaviour.destroyCancellationToken
MonoBehaviour.useGUILayout
MonoBehaviour.didStart
MonoBehaviour.didAwake
MonoBehaviour.runInEditMode
Behaviour.enabled
Behaviour.isActiveAndEnabled
Component.GetComponent<T>()
Component.TryGetComponent<T>(out T)
Component.GetComponentInChildren<T>()
Component.GetComponentsInChildren<T>()
Component.GetComponentInParent<T>()
Component.GetComponentsInParent<T>()
Component.GetComponents<T>()
Component.GetComponentIndex()
Component.CompareTag(TagHandle)
Component.transform
Component.transformHandle
Component.gameObject
Component.tag
Object.GetEntityId()
Object.GetInstanceID()
Object.GetHashCode()
Object.InstantiateAsync<T>(T)
Object.InstantiateAsync<T>(T, Transform)
Object.InstantiateAsync<T>(T, Vector3, Quaternion)
Object.InstantiateAsync<T>(T, Transform, Vector3, Quaternion)
Object.Instantiate(Object, Vector3, Quaternion)
Object.Instantiate(Object, Vector3, Quaternion, Transform)
Object.Instantiate(Object)
Object.Instantiate(Object, Scene)
Object.Instantiate<T>(T, InstantiateParameters)
Object.Instantiate<T>(T, Vector3, Quaternion, InstantiateParameters)
Object.Instantiate(Object, Transform)
Object.Instantiate<T>(T)
Object.Instantiate<T>(T, Vector3, Quaternion)
Object.Instantiate<T>(T, Vector3, Quaternion, Transform)
Object.Instantiate<T>(T, Transform)
Object.Destroy(Object)
Object.DestroyImmediate(Object)
Object.DontDestroyOnLoad(Object)
Object.DestroyObject(Object)
Object.FindObjectsOfType<T>()
Object.FindObjectsByType<T>(FindObjectsSortMode)
Object.FindObjectsByType<T>(FindObjectsInactive, FindObjectsSortMode)
Object.FindObjectOfType<T>()
Object.FindFirstObjectByType<T>()
Object.FindAnyObjectByType<T>()
Object.FindFirstObjectByType<T>(FindObjectsInactive)
Object.FindAnyObjectByType<T>(FindObjectsInactive)
Object.FindObjectsByType<T>()
Object.FindObjectsByType<T>(FindObjectsInactive)
Object.name
Object.hideFlags

Fields

BoundingBoxExtents

The extents (half-size) of the bounding box, calculated from BoundingBoxSize.

[HideInInspector]
public Vector3 BoundingBoxExtents

Field Value

Vector3

BoundingBoxSize

The size of the bounding box used for random spawn position selection.

public Vector3 BoundingBoxSize

Field Value

Vector3

GizmoColor

The color used to draw the spawner's gizmo in the editor.

public Color GizmoColor

Field Value

Color

InitialRespawnTime

The initial respawn time (in seconds) for spawned objects.

public float InitialRespawnTime

Field Value

float

InitialSpawnCount

The number of objects to spawn initially when the spawner starts.

public int InitialSpawnCount

Field Value

int

IsCacheDirty

Flag to track if the spawn chance cache needs updating.

[HideInInspector]
public bool IsCacheDirty

Field Value

bool

MaxSpawnCount

The maximum number of objects that can be spawned by this spawner.

[Tooltip("The maximum number of objects that can be spawned by this spawner.")]
public int MaxSpawnCount

Field Value

int

OrConditions

If any of these conditions return true, the object will respawn. This list is checked first (logical OR).

public List<BaseRespawnCondition> OrConditions

Field Value

List<BaseRespawnCondition>

PrewarmHeadroom

Extra instances reserved beyond MaxSpawnCount.

[Tooltip("Extra pooled instances beyond MaxSpawnCount, as slack for prefabs shared between spawners.")]
[Min(0)]
public int PrewarmHeadroom

Field Value

int

Remarks

Slack, not a requirement. A corpse holds its spawner slot for the whole of its decay — Despawn(ISpawnable) is what frees the slot and starts the respawn clock, and a corpse does not reach it until the decay timer expires — so this spawner can never have more than MaxSpawnCount live instances and the reservation alone would do.

The headroom is kept because the pool is shared: ObjectSpawnerPool de-duplicates reservations across every spawner using the same prefab, taking the largest single demand rather than the sum, so a prefab used by many spawners at once genuinely can need more instances than any one spawner reserved. This covers that without making the reservation quadratic.

PrewarmPool

When true, every prefab this spawner can produce is instantiated into the object pool at scene start, up to MaxSpawnCount each.

[Header("Pooling")]
[Tooltip("Instantiate this spawner's prefabs into the pool at scene start for a fixed memory footprint.")]
public bool PrewarmPool

Field Value

bool

Remarks

This is what makes a map's memory footprint deterministic. Without it the pool fills lazily — the first NPC of each kind is instantiated the moment a player walks into range — so a freshly loaded map hitches as it is explored and only reaches its true heap size once every spawner has fired at least once. Neither behaviour can be planned against.

Turn it off for spawners whose prefabs are large and rarely used, where paying the cost on demand is preferable to paying it always.

RandomRespawnTime

If true, a random respawn time is selected within the minimum and maximum range. Otherwise, the initial respawn time is used.

[Tooltip("If true a random number will be selected within the minimum and maximum range provided. Otherwise the maximum respawn time will be used.")]
public bool RandomRespawnTime

Field Value

bool

RandomSpawnPosition

If true, a random spawn position is picked inside the bounding box using the current position as the center.

[Tooltip("If true a random spawn position will be picked inside of the bounding box using the current position as the center.")]
public bool RandomSpawnPosition

Field Value

bool

RespawnCheckIntervalMaximum

Longest delay between respawn checks, in seconds.

[Tooltip("Longest delay between respawn checks, in seconds. Each check picks a fresh random delay in this range so spawners do not all poll on the same frame.")]
public float RespawnCheckIntervalMaximum

Field Value

float

RespawnCheckIntervalMinimum

Shortest delay between respawn checks, in seconds.

[Tooltip("Shortest delay between respawn checks, in seconds. Respawn deadlines are wall-clock, so this only sets how soon after a deadline the object appears - it does not change respawn timing itself.")]
public float RespawnCheckIntervalMinimum

Field Value

float

SchedulerIndex

This spawner's position in ObjectSpawnerScheduler's active list, or NotActive when it has no work outstanding.

[NonSerialized]
public int SchedulerIndex

Field Value

int

Remarks

Stored here so the scheduler can drop a spawner without searching for it. Owned by the scheduler; nothing else should write it.

SpawnType

The type of spawn selection (Linear, Random, Weighted).

public ObjectSpawnType SpawnType

Field Value

ObjectSpawnType

SpawnableRespawnTimers

List of respawn timers for each spawnable object.

public List<DateTime> SpawnableRespawnTimers

Field Value

List<DateTime>

Spawnables

The list of spawnable settings used to configure each spawnable object. Supports polymorphic subclasses via UnityEngine.SerializeReference for type-specific data injection.

[SerializeReference]
public List<SpawnableSettings> Spawnables

Field Value

List<SpawnableSettings>

Spawned

Dictionary of currently spawned objects, keyed by their unique ID.

public Dictionary<long, ISpawnable> Spawned

Field Value

Dictionary<long, ISpawnable>

SphereRadius

SphereCast radius used for spawning objects in the world.

[Tooltip("SphereCast radius used for spawning objects in the world.")]
public float SphereRadius

Field Value

float

Transform

Cached reference to the spawner's transform.

[HideInInspector]
public Transform Transform

Field Value

Transform

TrueConditions

All conditions must return true for the object to respawn. This list is checked second (logical AND).

public List<BaseRespawnCondition> TrueConditions

Field Value

List<BaseRespawnCondition>

UniqueSpawnables

When true, at most one live instance of each entry in Spawnables may exist at a time.

[Tooltip("Allow at most one live instance of each spawnable. Off by default. Turn on when every entry is a distinct individual that should never be duplicated.")]
public bool UniqueSpawnables

Field Value

bool

Remarks

Off by default, because the normal case is a spawner filling a zone with several of the same creature. Turn it on where each entry names a distinct individual — a zone listing several named NPCs would otherwise draw the same one repeatedly and stand two copies of it side by side, since the spawn index is chosen without regard to what is already alive.

This caps each entry at one, not the spawner: MaxSpawnCount still governs the total, so with this on the effective ceiling is the smaller of MaxSpawnCount and the number of assigned spawnables.

Methods

Despawn(ISpawnable)

Despawns the specified spawnable object, schedules its respawn, and removes it from the spawned dictionary.

public void Despawn(ISpawnable spawnable)

Parameters

spawnable ISpawnable

The spawnable object to despawn.

GetSpawnIndex()

Gets the index of the next spawnable to use, based on the configured spawn type.

public int GetSpawnIndex()

Returns

int

The index of the selected spawnable.

HasRespawnWork()

Whether this spawner has anything left to respawn.

public bool HasRespawnWork()

Returns

bool

True when a respawn is outstanding.

Remarks

Decides membership of ObjectSpawnerScheduler's active list, and so decides whether this spawner costs anything at all. A spawner at its cap or with no pending timers is not walked, which is the whole point: the cost of respawning scales with how much of the world is in motion rather than with how much of it exists.

OnStartNetwork()

Called when the network starts. Initializes spawner, validates spawnables, and spawns initial objects.

public override void OnStartNetwork()

OnStopNetwork()

Called when the network stops. Drops this spawner from the respawn schedule.

public override void OnStopNetwork()

Remarks

Without this a spawner in an unloaded scene stays queued and is woken against a destroyed object. The scheduler tolerates that, but leaving it to tolerate it means the heap carries entries for scenes that no longer exist.

SpawnObject()

Spawns a new object in the world using the selected spawnable settings and position logic.

public void SpawnObject()

TryRespawn()

Attempts to respawn objects if their timers have elapsed and respawn conditions are met.

public void TryRespawn()

Remarks

Public so anything holding a spawner can force an immediate attempt rather than waiting for its scheduled wake. The scheduler reaches the same work through RunScheduledRespawn(DateTime, float).