Class ObjectSpawnerScheduler
Runs the respawn checks for every ObjectSpawner that currently has something
to respawn, from one Update instead of one per spawner.
public static class ObjectSpawnerScheduler
- Inheritance
-
ObjectSpawnerScheduler
- Inherited Members
Remarks
The interval a spawner polls on is still its own — see
RespawnCheckIntervalMinimum. What changes here is which spawners
are asked at all. A spawner with nothing pending, which is most of them in a world at rest,
is not in the list and costs nothing whatsoever: not a check, not a gate comparison, and not
a Update dispatch.
The list holds references, not scheduling state. It is a plain List<T> of spawners with membership maintained by swap-removal, so a spawner occupies one reference while it has work and nothing at all when it does not. There is no ordering structure, no queued entries, and no per-spawner allocation. Measured against 100,000 spawners, whose own timer lists and spawned dictionaries come to roughly 107 MB, a membership list covering a tenth of them adds about 0.25 MB.
Fields
FramesPerSweep
How many frames one full pass over the active list is spread across.
public const int FramesPerSweep = 60
Field Value
Remarks
A spawner's own check interval is seconds long, so being visited within about a second costs nothing anybody can observe and keeps the per-frame walk proportional to a slice of the active list rather than all of it.
NotActive
The index stored on a spawner that is not currently in FishMMO.Shared.ObjectSpawnerScheduler.active.
public const int NotActive = -1
Field Value
Properties
ActiveCount
How many spawners currently have work outstanding. Exposed for tests and diagnostics.
public static int ActiveCount { get; }
Property Value
Methods
Clear()
Empties the active list. Intended for tests and for a clean shutdown between sessions.
public static void Clear()
Refresh(ObjectSpawner)
Brings spawner into or out of the active list to match whether it has
anything to respawn.
public static void Refresh(ObjectSpawner spawner)
Parameters
spawnerObjectSpawnerThe spawner whose membership should be refreshed.
Remarks
Call after anything that changes that: a despawn adding a respawn timer, a spawn consuming one, or the spawner reaching its cap and clearing them. Idempotent, so callers need not track whether the spawner was already in the list.
Tick(DateTime)
Gives every spawner with outstanding work the chance to run its respawn check.
public static void Tick(DateTime nowUtc)
Parameters
nowUtcDateTimeThe current UTC time, for evaluating respawn deadlines.
Remarks
Each spawner decides for itself whether its own interval has elapsed, so this walk is a float comparison per active spawner and nothing more. Spawners that finish their work leave the list here rather than being left to be skipped over on later frames.
Tick(DateTime, float)
Gives a slice of the spawners with outstanding work the chance to run their respawn check.
public static void Tick(DateTime nowUtc, float nowTime)
Parameters
nowUtcDateTimeThe current UTC time, for evaluating respawn deadlines.
nowTimefloatThe current UnityEngine.Time.time, for the interval gates.
Remarks
The list is swept rather than walked: each frame advances a cursor through a fraction of it, so every active spawner is visited about once per FramesPerSweep frames instead of every frame. Their own interval gate is measured in seconds (RespawnCheckIntervalMinimum), so visiting more often than that buys nothing — it only moves the cost from the spawners that have work to the ones that are merely waiting, which is most of them.
UnityEngine.Time.time is read once by the caller rather than by each spawner. It is a native property, and crossing into the engine per active spawner per frame cost more than everything else in this walk put together.
The dangling-reference check is ReferenceEquals(object, object) and
not == null on purpose. Unity overloads that operator to ask the engine whether the
native object is still alive, which is another crossing per entry per frame. Membership is
maintained on destruction instead, so a plain reference check is all this needs.
Unregister(ObjectSpawner)
Drops spawner from the active list.
public static void Unregister(ObjectSpawner spawner)
Parameters
spawnerObjectSpawnerThe spawner to drop.
Remarks
Call from OnStopNetwork, so a spawner in an unloaded scene is not walked and its
reference is not held.