Class ScyllaClock
Runtime, pure-C# wrapper around a registered ClockDefinition. Each instance owns a millisecond tick accumulator, an independent pause state, an independent TimeScaleModifierStack, a Scheduling.TickScheduler for absolute-time callbacks, a predicate-watcher list for condition-driven callbacks, and emits calendar boundary-crossing notifications when its date components roll over.
Implements
Inherited Members
Namespace: Scylla.Core.Time
Assembly: ScyllaCore.dll
Syntax
public sealed class ScyllaClock : IClockSource
Remarks
Constructed exclusively by RegisterClock(ClockDefinition). Game code reads or mutates clocks via the registry (GetClock(string)) but does not allocate them directly.
The effective tick advancement per call to Tick(float) is:
effectiveRate = BaseTickRate * (1 + SpeedMultiplier) * modifierStack.GetMultiplier()
* (RespectsGlobalTimeScale ? source.TimeScale : 1)
deltaMs = round(unscaledDeltaTime * 1000 * effectiveRate) -- double precision, saturating
When the clock is paused (own pause flag OR RespectsGlobalPause
AND the global source is paused), no advancement occurs. Negative effective rates produce
negative deltaMs and run the clock backward. When
DeterministicMode is on, the incoming delta is replaced by
DeterministicStepSeconds for lockstep / replay use.
On each advancing tick the dispatch order is: boundary events (if calendar assigned), scheduler sweep, WaitUntil sweep, optional tick event, optional rate-change event. The modifier stack is updated before the pause check so timed effects expire even while the clock is paused.
Properties
BaseTickRate
Read-only base tick rate from the definition.
Declaration
public float BaseTickRate { get; }
Property Value
| Type | Description |
|---|---|
| float |
Calendar
The clock's calendar.
Declaration
public CalendarDefinition Calendar { get; }
Property Value
| Type | Description |
|---|---|
| CalendarDefinition |
ClockID
Unique identifier for this clock (matches ClockID).
Declaration
public string ClockID { get; }
Property Value
| Type | Description |
|---|---|
| string |
CurrentDate
Resolved current date computed from CurrentTickMilliseconds. Reuses the per-tick cache populated by Tick(float) when the tick value matches the cached value, so back-to-back property reads (e.g. from a debug overlay) avoid re-running TickToDate(long, CalendarDefinition).
Declaration
public GameDate CurrentDate { get; }
Property Value
| Type | Description |
|---|---|
| GameDate |
CurrentPauseMode
Per-clock pause mode for IClockSource consumers. Returns None when not paused, Hard when paused either by the clock's own Pause() call or by the global Hard pause; the Soft mode of the global source is mirrored only when this clock RespectsGlobalPause.
Declaration
public PauseMode CurrentPauseMode { get; }
Property Value
| Type | Description |
|---|---|
| PauseMode |
CurrentTickMilliseconds
Canonical millisecond tick accumulator. Negative values represent dates before the calendar epoch.
Declaration
public long CurrentTickMilliseconds { get; }
Property Value
| Type | Description |
|---|---|
| long |
Definition
The originating ClockDefinition asset.
Declaration
public ClockDefinition Definition { get; }
Property Value
| Type | Description |
|---|---|
| ClockDefinition |
DisplayName
Human-readable display name.
Declaration
public string DisplayName { get; }
Property Value
| Type | Description |
|---|---|
| string |
EffectiveRate
Computed effective in-game seconds per real second for this clock, accounting for the own pause flag, the global pause state, the speed multiplier, the per-clock modifier stack, and the optional global time-scale influence.
Declaration
public float EffectiveRate { get; }
Property Value
| Type | Description |
|---|---|
| float |
|
IsMasterClock
Whether this clock is the project's master clock.
Declaration
public bool IsMasterClock { get; }
Property Value
| Type | Description |
|---|---|
| bool |
IsPaused
Independent pause flag for this clock.
Declaration
public bool IsPaused { get; }
Property Value
| Type | Description |
|---|---|
| bool |
IsPausedOwn
The clock's own pause flag, ignoring whether the global ScyllaTime is paused. Useful for snapshot capture: we want to restore the clock's intent, not the global pause state's effect on it.
Declaration
public bool IsPausedOwn { get; }
Property Value
| Type | Description |
|---|---|
| bool |
IsReversed
True when EffectiveRate is currently negative.
Declaration
public bool IsReversed { get; }
Property Value
| Type | Description |
|---|---|
| bool |
ModifierStack
Per-clock modifier stack for hit-stop, slow-mo, and other layered rate effects.
Exposed primarily for snapshot/restore (RestoreState(MasterTimeState)) and
TimeEffects internal use; game code should prefer the convenience methods
PushModifier(TimeScaleModifier), PopModifier(TimeScaleModifierHandle), ClearModifiers(),
and RemoveModifiersBySourceID(string) for direct mutation.
Declaration
public TimeScaleModifierStack ModifierStack { get; }
Property Value
| Type | Description |
|---|---|
| TimeScaleModifierStack |
PendingScheduledCount
Number of currently-pending scheduled entries on this clock (TickScheduler entries plus active WaitUntil watchers). Useful for debug overlays.
Declaration
public int PendingScheduledCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
SpeedMultiplier
Mutable speed multiplier applied on top of BaseTickRate.
A value of 0 means the clock runs at exactly its base rate;
-1 stops the clock; values below -1 run backward.
The effective rate formula is BaseTickRate * (1 + SpeedMultiplier) before
modifier-stack and global scale factors are applied.
Declaration
public float SpeedMultiplier { get; set; }
Property Value
| Type | Description |
|---|---|
| float |
TimeScale
Effective time scale exposed for IClockSource consumers.
Declaration
public float TimeScale { get; }
Property Value
| Type | Description |
|---|---|
| float |
UnscaledDeltaTime
Real seconds elapsed since the last Tick(float), unaffected by pause or scale.
Declaration
public float UnscaledDeltaTime { get; }
Property Value
| Type | Description |
|---|---|
| float |
Methods
CancelScheduled(ScheduledTickHandle)
Cancels a scheduled callback returned by Scheduling.ScheduleExtensions.RunAfter, Scheduling.ScheduleExtensions.RunEvery, Scheduling.ScheduleExtensions.RunAtDate, or Scheduling.ScheduleExtensions.WaitUntil. Equivalent to calling Scheduling.ScheduleExtensions.Cancel.
Declaration
public bool CancelScheduled(ScheduledTickHandle handle)
Parameters
| Type | Name | Description |
|---|---|---|
| ScheduledTickHandle | handle |
Returns
| Type | Description |
|---|---|
| bool |
ClearModifiers()
Removes every modifier from this clock's stack.
Declaration
public void ClearModifiers()
ClearScheduled()
Removes every scheduled callback and predicate watcher from this clock.
Declaration
public void ClearScheduled()
Pause()
Pauses this clock independently of the global ScyllaTime.
Declaration
public void Pause()
PopModifier(TimeScaleModifierHandle)
Removes a previously pushed modifier from this clock's stack.
Declaration
public bool PopModifier(TimeScaleModifierHandle handle)
Parameters
| Type | Name | Description |
|---|---|---|
| TimeScaleModifierHandle | handle |
Returns
| Type | Description |
|---|---|
| bool |
PushModifier(TimeScaleModifier)
Pushes a per-clock TimeScaleModifier onto this clock's stack.
Declaration
public TimeScaleModifierHandle PushModifier(TimeScaleModifier modifier)
Parameters
| Type | Name | Description |
|---|---|---|
| TimeScaleModifier | modifier |
Returns
| Type | Description |
|---|---|
| TimeScaleModifierHandle |
RegisterListener(IClockListener)
Registers a hot-path observer for this clock's events. Unlike
RegisterListener(ITimeListener), this overload deliberately omits a
Log.Debug entry: per-clock listeners are typically registered frequently from
gameplay code and the diagnostic log would produce noise without adding value.
Declaration
public void RegisterListener(IClockListener listener)
Parameters
| Type | Name | Description |
|---|---|---|
| IClockListener | listener |
RemoveModifiersBySourceID(string)
Removes every modifier whose SourceID equals
sourceID. Returns the count removed. Preferred over reaching
into ModifierStack directly.
Declaration
public int RemoveModifiersBySourceID(string sourceID)
Parameters
| Type | Name | Description |
|---|---|---|
| string | sourceID |
Returns
| Type | Description |
|---|---|
| int |
Resume()
Resumes this clock independently of the global ScyllaTime.
Declaration
public void Resume()
SetCurrentDate(GameDate)
Replaces the clock's current date by computing the matching tick value from
date. The supplied date's CalendarHash
must match this clock's calendar.
Declaration
public void SetCurrentDate(GameDate date)
Parameters
| Type | Name | Description |
|---|---|---|
| GameDate | date |
SetSpeedMultiplier(float)
Sets SpeedMultiplier. Provided for symmetry with SetTimeScale(float).
Declaration
public void SetSpeedMultiplier(float multiplier)
Parameters
| Type | Name | Description |
|---|---|---|
| float | multiplier |
TogglePause()
Toggles this clock's pause state. Consults the public IsPaused property (which OR's the own-pause flag with the global pause) so toggling during a global pause does not silently set a sticky own-pause that would survive after the global pause lifts.
Declaration
public void TogglePause()
UnregisterListener(IClockListener)
Unregisters a previously registered hot-path observer. See RegisterListener(IClockListener) for the no-debug-log rationale.
Declaration
public void UnregisterListener(IClockListener listener)
Parameters
| Type | Name | Description |
|---|---|---|
| IClockListener | listener |