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.
- Convenience helper that returns query.GetSingleton
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.