Skip to content

Game.TimeSystem

Assembly: Assembly-CSharp (typical Unity game assembly)
Namespace: Game.Simulation

Type: class

Base: GameSystemBase (implements ITimeSystem, IPostDeserialize)

Summary:
TimeSystem manages the in-game simulation time and date for Cities: Skylines 2. It converts the simulation frame index (from SimulationSystem) into normalized day/time values, computes year/day offsets, and exposes helper methods to obtain DateTime values for rendering or gameplay use. The system reads time configuration from a TimeSettingsData singleton and stores persistent offsets in a TimeData entity. Key behaviors: - Uses a fixed tick resolution: kTicksPerDay = 262144 ticks per day. - Exposes normalizedTime (time of day) and normalizedDate (time of year) and the current year. - During deserialization it ensures a TimeData entity exists and initializes start-frame/starting year for new games. - Updates its cached time values each frame in UpdateTime() (called from OnUpdate).


Fields

  • private SimulationSystem m_SimulationSystem
    Reference to the simulation system used to read the current simulation frame index (frame-based time source).

  • public const int kTicksPerDay = 262144
    Constant tick count representing one in-game day. Used throughout time calculations.

  • private float m_Time
    Cached normalized time-of-day [0..1) for the current simulation frame (updated in UpdateTime()).

  • private float m_Date
    Cached normalized time-of-year [0..1) (updated in UpdateTime()).

  • private int m_Year = 1
    Cached current year (initialized to 1, updated in UpdateTime()).

  • private int m_DaysPerYear = 1
    Cached days-per-year value. Lazily read from TimeSettingsData if zero.

  • private uint m_InitialFrame
    An unsigned integer intended to store an initial frame index. Present in the class but not used directly in other methods in this file.

  • private EntityQuery m_TimeSettingGroup
    EntityQuery that selects the TimeSettingsData singleton used to configure days per year and other settings.

  • private EntityQuery m_TimeDataQuery
    EntityQuery that selects the TimeData singleton which stores persistent time offsets and starting-frame data.

Properties

  • public int startingYear { get; set; }
    Public property that holds the starting year for new games. When creating a new game during PostDeserialize, this is written into the TimeData singleton.

  • public float normalizedTime => m_Time
    Read-only property exposing the cached normalized time-of-day (0..1). Use for UI, rendering and other time-dependent logic.

  • public float normalizedDate => m_Date
    Read-only property exposing the cached normalized time-of-year (0..1).

  • public int year => m_Year
    Read-only property exposing the cached current year.

  • public int daysPerYear
    Read-only property that returns the number of days per year. If m_DaysPerYear is zero the value is fetched from the TimeSettingsData singleton and clamped to at least 1.

Constructors

  • public TimeSystem()
    Default constructor. Marked with [Preserve] in source to prevent stripping; no initialization beyond field defaults. The real initialization occurs in OnCreate().

Methods

  • protected override void OnCreate()
    Initializes the system: gets/creates the SimulationSystem, sets up EntityQuery objects (TimeSettingsData and TimeData), and requires those queries for update (RequireForUpdate). Called when the system is created.

  • public void PostDeserialize(Context context)
    Called after serialization/deserialization. Ensures a TimeData entity exists, initializes TimeData fields for new games (sets m_FirstFrame to the current simulation frame and m_StartingYear from startingYear), and calls UpdateTime() to populate cached time fields.

  • protected int GetTicks(uint frameIndex, TimeSettingsData settings, TimeData data)
    Compute total tick count relative to a TimeData.m_FirstFrame using an explicit frameIndex. Adds TimeOffset and date offset contributions. Returns ticks as an int.

  • protected int GetTicks(TimeSettingsData settings, TimeData data)
    Same as above but uses the current simulation frame from m_SimulationSystem.frameIndex.

  • protected double GetTimeWithOffset(TimeSettingsData settings, TimeData data, double renderingFrame)
    Returns a double representing the rendering frame plus time and date offsets (in ticks). Used as helper for fractional time calculations.

  • public float GetTimeOfDay(TimeSettingsData settings, TimeData data, double renderingFrame)
    Public helper that returns the time-of-day [0..1) for a given rendering frame (accounts for TimeData offsets).

  • protected float GetTimeOfDay(TimeSettingsData settings, TimeData data)
    Returns the time-of-day [0..1) for the current simulation frame.

  • public float GetTimeOfYear(TimeSettingsData settings, TimeData data, double renderingFrame)
    Returns normalized time-of-year [0..1) for a given rendering frame. Takes days-per-year into account.

  • protected float GetTimeOfYear(TimeSettingsData settings, TimeData data)
    Returns normalized time-of-year [0..1) for the current simulation frame.

  • public float GetElapsedYears(TimeSettingsData settings, TimeData data)
    Returns the number of elapsed years (floating-point) since TimeData.m_FirstFrame based on tick counts and days-per-year.

  • public float GetStartingDate(TimeSettingsData settings, TimeData data)
    Returns the starting normalized date-of-year (based on data stored in TimeData and TimeSettingsData).

  • public int GetYear(TimeSettingsData settings, TimeData data)
    Compute the integer year given settings and TimeData (adds data.m_StartingYear and the number of full years elapsed since m_FirstFrame).

  • public static int GetDay(uint frame, TimeData data)
    Static helper to get the integer day count since m_FirstFrame using a frame index and data.TimeOffset. Returns floor((frame - firstFrame)/ticksPerDay + TimeOffset).

  • public void DebugAdvanceTime(int minutes)
    Debug helper that advances in-game time by a number of minutes by subtracting from TimeData.m_FirstFrame (effectively fast-forwarding). Useful for testing.

  • private static DateTime CreateDateTime(int year, int day, int hour, int minute, float second)
    Constructs a UTC DateTime from year/day/hour/minute/second values. Applies daylight-saving-time correction (adds an hour if the resulting DateTime falls into DST). Used by GetDateTime/GetCurrentDateTime to create real DateTime instances from normalized values.

  • public DateTime GetDateTime(double renderingFrame)
    Returns a DateTime corresponding to a given rendering frame (fractional frame), factoring in TimeSettingsData and TimeData offsets. Converts normalized time-of-day and time-of-year into concrete year/day/hour/minute/second values.

  • public DateTime GetCurrentDateTime()
    Returns a DateTime built from the cached normalizedTime, normalizedDate and year. Useful for code that needs the current in-game wall-clock time.

  • protected override void OnUpdate()
    Called each frame by the ECS world. Calls UpdateTime() to refresh cached values.

  • private void UpdateTime()
    Internal method that reads the TimeSettingsData and TimeData singletons and updates m_Time, m_Date, m_Year and m_DaysPerYear fields.

Usage Example

[Preserve]
protected override void OnCreate()
{
    base.OnCreate();
    // Example: get a reference to the TimeSystem and query current DateTime
    var timeSystem = World.GetOrCreateSystemManaged<Game.Simulation.TimeSystem>();
    DateTime current = timeSystem.GetCurrentDateTime();
    Debug.Log($"In-game date/time: {current.ToString("u")}");
}

Notes and tips: - kTicksPerDay (262144) is used as the base resolution for fractional day calculations; many methods rely on this constant. - TimeSettingsData.m_DaysPerYear configures the number of days in a year; ensure this singleton exists (the system requires it). - TimeData stores m_FirstFrame, TimeOffset, date offsets and m_StartingYear; PostDeserialize ensures it's created on load. - DateTime values produced by the system use UTC as a base and apply a daylight-saving hour if the computed DateTime would be in DST.