Files
Sebastian Bularca 90b66f26fd dadded package sync
2026-04-12 19:22:35 +02:00
..
2026-04-12 19:14:37 +02:00
2026-04-12 19:14:37 +02:00
2026-04-12 19:19:04 +02:00
2026-04-12 19:14:37 +02:00
2026-04-12 19:22:35 +02:00
2026-04-12 19:22:35 +02:00
2026-04-12 19:14:37 +02:00
2026-04-12 19:14:37 +02:00
2026-04-12 19:14:37 +02:00
2026-04-12 19:14:37 +02:00

Jovian Calendar

A configurable in-game calendar and world clock system for Unity. Supports custom day lengths, hours, minutes, months with variable lengths, named months, week tracking, and a serializable date-time struct. No external dependencies.

Requirements

  • Unity 2022.3 or later
  • No additional package dependencies

Quick Start

1. Create a CalendarSettings asset

In the Unity Editor, go to Assets > Create > Jovian > Calendar > Calendar Settings.

Configure:

  • Seconds Per Full Day: How many real-time seconds equal one full in-game day (the 0-1 cycle)
  • Hours Per Day: In-world hours per day (e.g. 24)
  • Minutes Per Hour: In-world minutes per hour (e.g. 60)
  • Days Per Month: Array defining the length of each month. Array length = months per year
  • Month Names: Display names for each month (must match Days Per Month length)
  • Days Per Week: Optional week length (0 to disable)
  • Start Date: Starting year, month, day, hour, minute for the clock

2. Create and tick a WorldClock

using Jovian.Calendar;

// Create the clock from settings
var clock = new WorldClock(calendarSettings);

// Each frame, feed it a 0-1 normalized day progress
clock.Tick(normalizedDayTime);

// Query the current date and time
WorldDateTime now = clock.Now;
Debug.Log($"Year {now.year}, {clock.GetMonthName()} {now.DisplayDay}, {now.TimeString}");

3. Display the date

// Individual fields
int year = clock.Now.year;
int month = clock.Now.DisplayMonth; // 1-indexed
int day = clock.Now.DisplayDay;     // 1-indexed
string time = clock.Now.TimeString; // "HH:MM"

// Full display string
string full = clock.FullStringNamed();
// e.g. "14:30, 5th day of Frostmoon, year 3"

CalendarSettings

ScriptableObject defining calendar rules. Create via Assets > Create > Jovian > Calendar > Calendar Settings.

Field Type Description
secondsPerFullDay float Real-time seconds for one full 0-1 day cycle
hoursPerDay int In-world hours per day
minutesPerHour int In-world minutes per hour
daysPerMonth int[] Days in each month. Array length = months per year
monthNames string[] Display name per month. Must match daysPerMonth length
daysPerWeek int Days per week (0 to disable week tracking)
startYear int Starting year
startMonth int Starting month (0-indexed)
startDay int Starting day (0-indexed)
startHour int Starting hour
startMinute int Starting minute

Computed properties:

  • MonthsPerYear -- derived from daysPerMonth array length
  • TotalDaysInYear -- sum of all daysPerMonth entries
  • MinutesPerDay -- hoursPerDay * minutesPerHour

WorldClock

The core clock class. Feed it a normalized 0-1 day progress each tick. It accumulates world-minutes internally, handling day wrap-around and fractional minute accumulation across frames.

var clock = new WorldClock(settings);

// Tick with normalized time (0 = midnight, 0.5 = noon, 1 = next midnight)
clock.Tick(normalizedTime);

// Manual time skip (sleep, rest, cutscene)
clock.AdvanceMinutes(480); // skip 8 hours

// Queries
WorldDateTime now = clock.Now;
long elapsed = clock.TotalElapsedMinutes;
float normalized = clock.NormalizedTimeOfDay; // 0-1 for lighting/skybox
int weekday = clock.DayOfWeek; // 0-indexed, -1 if disabled
string monthName = clock.GetMonthName();
string display = clock.FullStringNamed();

WorldDateTime

A serializable struct representing a point in calendar time. Implements IEquatable<WorldDateTime> and IComparable<WorldDateTime> for collections and sorting.

WorldDateTime dt = clock.Now;

// 0-indexed fields
dt.year;   dt.month;   dt.day;   dt.hour;   dt.minute;

// 1-indexed display properties
dt.DisplayDay;    // day + 1
dt.DisplayMonth;  // month + 1

// Formatting
dt.TimeString;    // "14:30"
dt.DateString;    // "5/3/1"
dt.FullString;    // "5/3/1 14:30"

// Comparison
if(dateA < dateB) { ... }
if(dateA == dateB) { ... }
var sorted = dates.OrderBy(d => d);

Integration Example

// In your game state initialization:
var calendarSettings = Addressables.LoadAssetAsync<CalendarSettings>("CalendarSettings").WaitForCompletion();
var worldClock = new WorldClock(calendarSettings);

// In your time handler's Tick():
float normalizedTime = localTime / dayLength;
worldClock.Tick(normalizedTime);

// Update UI:
dayText.text = $"Day {worldClock.Now.DisplayDay}, {worldClock.GetMonthName()}";

// Use NormalizedTimeOfDay for visual effects:
float t = worldClock.NormalizedTimeOfDay;
skyboxMaterial.SetFloat("_Blend", t);
directionalLight.intensity = sunCurve.Evaluate(t);

API Reference

Type Description
CalendarSettings ScriptableObject defining calendar rules (day length, months, weeks, start date)
WorldClock Core clock class. Tick with normalized time, query WorldDateTime
WorldDateTime Serializable struct for date-time values. IEquatable, IComparable, operator overloads