Skip to content

Game.EndFrameBarrier

Assembly:
Namespace:

Type:

Base:

Summary: This documentation actually describes the struct Game.Common.TimeData (from the provided Game\Common\TimeData.cs). TimeData is a small ECS component used to represent the world's starting time and date information for Cities: Skylines 2. It stores the first frame index, starting year/month/hour/minutes and provides helpers to convert between a normalized time-of-day float and the stored hour/minute values, to (de)serialize the values, and to obtain a singleton from an EntityQuery.


Fields

  • private System.Diagnostics.Stopwatch m_Stopwatch This field is not present in TimeData. The actual fields in TimeData are:
  • uint m_FirstFrame — index of the first frame (typically 0 when initialized).
  • int m_StartingYear — the starting year (e.g., 2021).
  • byte m_StartingMonth — the starting month (1–12, here default is 5).
  • byte m_StartingHour — the starting hour (0–23).
  • byte m_StartingMinutes — the starting minutes (0–59). These fields represent the initial in-game date/time and are serialized/deserialized in that order.

  • private Unity.Jobs.JobHandle <producerHandle>k__BackingField This field is not present in TimeData. TimeData has no JobHandle or stopwatch; it is a plain value-type ECS component that implements serialization interfaces (IDefaultSerializable, ISerializable) and can be used as a query singleton.

Properties

  • public Unity.Jobs.JobHandle producerHandle { get; private set } TimeData does not expose a producerHandle property. The actual property on TimeData is:

  • float TimeOffset { get; set; }

Description: - Getter: returns a normalized time-of-day as a float in [0,1) computed from m_StartingHour and m_StartingMinutes: (m_StartingHour / 24f) + (m_StartingMinutes / 1440f) + 1e-05f Note: the small 1E-05f offset is added in the getter to avoid returning an exact boundary (likely to prevent edge cases where 0 or exact multiples are problematic). - Setter: accepts a normalized time-of-day float (typically in [0,1)) and sets m_StartingHour and m_StartingMinutes: m_StartingHour = FloorToInt((value * 24f + 1E-05f) % 24f) m_StartingMinutes = (byte)(RoundToInt(value * 1440f) % 60)

Behavior notes: - The setter uses modulo (%) so values outside [0,1) will wrap around by day. - Minutes are computed by rounding value1440 to nearest integer then taking mod 60 (so minute rounding may push hour boundaries; hours are computed using floor on value24). - The epsilon 1E-05f is applied to avoid exactness issues.

Additional small helper: - float GetDateOffset(int daysPerYear) - Returns a normalized offset for the starting month relative to a year length in days: return m_StartingMonth / (float)daysPerYear

Constructors

  • public EndFrameBarrier() TimeData is a struct and has the default parameterless value-type constructor generated by C#. There is no explicit constructor in the source. Instead, there is a SetDefaults(Context) method that initializes fields to sane defaults:

  • SetDefaults sets: m_FirstFrame = 0 m_StartingYear = 2021 m_StartingMonth = 5 (May) m_StartingHour = 7 m_StartingMinutes = 0

Use SetDefaults to initialize a newly created TimeData instance to the game's defaults when creating or resetting world state.

Methods

  • protected virtual OnCreate() : System.Void TimeData does not have an OnCreate method. The actual methods defined on TimeData are:

  • void SetDefaults(Context context)

    • Initializes the component to default values listed above. Intended to be used when a component needs default population (via the IDefaultSerializable interface).
  • void Deserialize(TReader reader) where TReader : IReader

    • Reads the fields from the reader in the following order: m_FirstFrame (uint) m_StartingYear (int) m_StartingMonth (byte) m_StartingHour (byte) m_StartingMinutes (byte)
    • Important: The reading order must match the writer order used in Serialize.
  • void Serialize(TWriter writer) where TWriter : IWriter

    • Writes the fields to the writer in the same order as Deserialize: m_FirstFrame, m_StartingYear, m_StartingMonth, m_StartingHour, m_StartingMinutes
  • static TimeData GetSingleton(EntityQuery query)

    • Convenience helper that returns query.GetSingleton() if the query is not empty (IsEmptyIgnoreFilter == false); otherwise returns default(TimeData).
    • Use this to safely obtain the TimeData singleton component from an ECS query without throwing when the query is empty.

Usage Example

// Example: creating and initializing TimeData, reading/writing time-of-day, and getting a singleton.

TimeData td = default;
td.SetDefaults(default); // initialize to defaults: 2021-05-07:00

// Read normalized time-of-day (float in [0,1)):
float timeOfDay = td.TimeOffset; // e.g. 7:00 -> ~0.29167 (+1e-5)

// Set time-of-day using normalized value
td.TimeOffset = 0.5f; // sets hour/minute to roughly 12:00 (noon)

// Convert month into a normalized date offset (requires days-per-year)
int daysPerYear = 365;
float monthOffset = td.GetDateOffset(daysPerYear); // e.g. m_StartingMonth / 365f

// Serialization sample (using the game's IWriter/IReader implementations)
using (var writer = /* obtain IWriter */ null)
{
    // writer must be a valid IWriter instance provided by the serialization system
    // td.Serialize(writer);
}

// Obtaining the TimeData singleton from an EntityQuery
EntityQuery query = /* build query that matches the singleton component */;
TimeData singleton = TimeData.GetSingleton(query);
if (!query.IsEmptyIgnoreFilter)
{
    // safe to use singleton
}

Notes and tips: - Ensure Serialize and Deserialize are used with matching reader/writer implementations and that the order of fields is preserved. - The TimeOffset property uses an epsilon (1E-05f) to avoid exact boundary values; be mindful when comparing floating-point times. - GetSingleton returns default(TimeData) if the query is empty — check query.IsEmptyIgnoreFilter if you need to know whether a valid singleton existed.