Sistema de Temporitzadors

Un registre de temporitzadors amb nom que centralitza el ticking per fotograma, permet a cada temporitzador triar entre temps escalat o no escalat, i manté en un únic lloc el temps de sessió, la pausa i el timing de cinemàtiques.

Per a què serveix aquest sistema

Tot joc necessita temporitzadors. Cooldowns, comptes enrere, rellotges de sessió, retards de cinemàtica — tots acaben dispersos en diferents MonoBehaviours, cadascun amb la seva pròpia lògica d'Update i cadascun decidint per separat si respectar Time.timeScale o no. Aquesta comptabilitat dispersa es converteix en un problema en el moment en què cal pausar el joc, saltar-se una cinemàtica o lliurar el temps transcorregut a un sistema d'analítiques.

El mòdul Timer de Serenity substitueix aquesta dispersió amb un únic registre ITimerService. Els sistemes registren temporitzadors amb nom, escullen un mode de temps i criden start, stop o reset. El servei actualitza tots els temporitzadors registrats un cop per fotograma des d'un punt únic, llegint el delta a través d'un ITimeProvider injectat perquè la dependència de Unity no filtri mai al domini.

El problema a Unity

El patró habitual és copiar la mateixa lògica de compte enrere o temps transcorregut a cada sistema que la necessita. Cada còpia té la seva pròpia crida a Time.deltaTime o Time.unscaledDeltaTime, la seva pròpia bandera d'execució i la seva pròpia lògica de reset. Quan arriba un nou requisit — la pausa ha de congelar els cooldowns però no el rellotge de sessió, o una cinemàtica necessita progrés en temps real — cal canviar cada còpia. Els bugs que s'introdueixen en oblidar-ne alguna són difícils de rastrejar perquè res no uneix els temporitzadors entre si.

Sense una capa compartida de temporitzadors, coordinar el temps transcorregut de Game Session, la pausa de Game Mode i una seqüència de cinemàtica exigeix o un acoblament estret entre aquests sistemes o una altra ronda de comptabilitat de temps duplicada. Cap de les dues opcions escala.

Com ho aborda Serenity

Serenity modela el domini del temporitzador a través d'ITimerService, ITimer i TimerFactory. ITimerService és el registre: crea temporitzadors amb AddTimer, els recupera per nom amb GetTimer, els elimina amb RemoveTimer i els actualitza tots amb una única crida a UpdateTimers. ITimer representa un temporitzador individual: exposa SetTimer, StartTimer, StopTimer, GetTimeInSeconds i el punt d'entrada per fotograma Tick. TimerFormatterService converteix segons bruts en cadenes formatades d'hores, minuts i segons per mostrar a la pantalla.

L'escalat de temps es controla per temporitzador a través de l'enum TimeMode. Els temporitzadors TimeMode.Scaled avancen amb Time.deltaTime i es pausen automàticament quan timeScale arriba a zero. Els temporitzadors TimeMode.Unscaled avancen amb el delta en temps real i continuen executant-se durant la pausa. ITimeProvider abstrau aquest delta del domini perquè la capa de Unity es pugui substituir o simular en proves.

Com encaixa a Serenity

El mòdul Timer viu al namespace Serenity.Timer i segueix l'estructura per capes de la foundation. La capa de Domini conté l'enum TimeMode i TimerFormatterService. La capa d'Aplicació defineix ITimer, ITimerService, TimerFactory i ITimerServiceFactory. La capa d'Infraestructura proporciona UnityTimer, UnityTimerService, UnityTimerFactory i UnityTimeProvider, que connecten les interfícies del domini amb l'API de temps de Unity. UnityTimerInstaller registra el servei a la pipeline d'inicialització.

Timer coopera amb Game Session, que és el propietari del temporitzador de temps transcorregut de sessió i, per tant, el consumidor principal d'AddTimer en l'arrencada. Game Mode senyalitza la pausa canviant timeScale, la qual cosa atura automàticament tots els temporitzadors Scaled sense cap lògica de pausa específica de Timer. Els sistemes de seqüència i cinemàtica poden registrar temporitzadors Unscaled per rastrejar el progrés en temps real de manera independent a la velocitat del joc.

Flux de treball pràctic

  1. Resol ITimerService a través de l'instal·lador i crida AddTimer amb un identificador de cadena i un TimeMode per registrar un nou temporitzador.
  2. Crida StartTimer sobre l'ITimer retornat per començar a avançar-lo a cada fotograma.
  3. Crida UpdateTimers un cop per fotograma des del game loop — el servei llegeix el delta d'ITimeProvider i actualitza tots els temporitzadors registrats.
  4. Recupera qualsevol temporitzador per nom amb GetTimer i llegeix el seu valor actual mitjançant GetTimeInSeconds o els accessors individuals GetHours, GetMinutes i GetSeconds.
  5. Fes servir TimerFormatterService per formatar segons bruts en una cadena de visualització per a etiquetes de compte enrere o temps transcorregut a la UI.
  6. Crida StopTimer per pausar un temporitzador concret, ResetTimer per retornar-lo a la seva durada configurada i RemoveTimer per desregistrar-lo quan el sistema propietari s'apaga.

Què inclou

  • Registre de temporitzadors amb nom a través d'ITimerService amb AddTimer, GetTimer, RemoveTimer i GetAllTimers
  • Selecció de mode de temps per temporitzador mitjançant TimeMode.Scaled i TimeMode.Unscaled
  • Ticking centralitzat per fotograma a través d'UpdateTimers — els sistemes individuals no implementen la seva pròpia comptabilitat de temps
  • Abstracció ITimeProvider que manté l'API de temps de Unity fora de la capa de domini
  • Interfície ITimer amb SetTimer, StartTimer, StopTimer i GetTimeInSeconds
  • TimerFormatterService per convertir segons bruts en cadenes de visualització en format HH:MM:SS
  • TimerFactory i ITimerServiceFactory per crear instàncies de temporitzador sense acoblament a Unity
  • Integració amb Game Session per al temps transcorregut i amb Game Mode per a la pausa a través de timeScale

Quan fer-lo servir

  • Projectes que necessiten múltiples temporitzadors amb nom — cooldowns, rellotges de sessió, comptes enrere — gestionats des d'un únic lloc en lloc de dispersos entre MonoBehaviours.
  • Jocs on la pausa ha de congelar alguns temporitzadors però no d'altres, la qual cosa requereix un control explícit del temps escalat enfront del no escalat per temporitzador.
  • Bases de codi on les cinemàtiques o seqüències necessiten rastrejar el progrés en temps real de manera independent a la velocitat del joc.
  • Equips que volen la lògica de temporitzadors testejable en C# pur sense dependre de l'API de temps de Unity a la capa de domini.

Sistemes relacionats

Utilitza Serenity quan vulguis que cada temporitzador del joc estigui registrat, amb nom i actualitzat des d'un punt únic, amb cada temporitzador decidint per si mateix si la pausa significa aturar-se — i sense que res d'aquesta lògica filtri al domini.

Tornar a la pàgina principal