Sistema de Moviment sobre Rails

Un servei de rails passiu basat en snapshots que rastreja el progrés normalitzat de 0 a 1 al llarg de camins de nodes amb nom, mantenint els sistemes de moviment, IA i càmera completament desacoblats.

Per a què serveix aquest sistema

El moviment sobre rails sembla senzill fins que la càmera, el controlador del jugador, el director d'IA i el seqüenciador de cinemàtiques necessiten llegir la mateixa posició del camí sense trepitjar-se entre si. Un MonoBehaviour que posseeix el transform i emet esdeveniments sembla funcionar al principi, però col·lapsa en el moment que dos sistemes necessiten escriure o llegir el progrés al mateix frame.

El mòdul Game Rail de Serenity resol això separant l'estat del camí de la seva visualització. Un únic servei posseeix el progrés normalitzat per a cada rail amb nom. Qualsevol sistema que necessiti saber on és alguna cosa crida GetSnapshot i llegeix un valor immutable. Ningú no lluita per la propietat.

El problema a Unity

El moviment sobre rails a Unity sol acabar com un únic component que mou un transform, dispara esdeveniments als waypoints i intenta ser la font de veritat per a posició, progrés i finalització. Quan apareix un segon consumidor —un rig de càmera, un enemic que emmiralla el camí del jugador, una barra de progrés a la UI, un disparador de cinemàtiques— el component acumula condicionals, camps exposats i referències directes que el fan impossible de reutilitzar entre escenes.

El problema de fons és acoblar l'estat a la visualització. En el moment que un MonoBehaviour posseeix tant el valor de progrés com el transform que mou, les proves i la reutilització es tornen impracticables. Els canvis de game mode, els reinicis del spawner i les transicions entre escenes necessiten restablir o inspeccionar el progrés des de fora, i un component autocontingut no té una superfície neta per a això.

Com ho aborda Serenity

Serenity exposa l'estat dels rails a través d'IGameRailService, que inclou ConfigureRail i RegisterRail per definir camins amb nom a partir de RailPathConfig o arrays de RailNodePosition, AdvanceProgress i SetProgress per escriure deltes de moviment normalitzats, GetProgress per llegir un value object RailProgress i GetSnapshot per obtenir un RailSnapshot immutable que conté la identitat del rail, el progrés actual i el nombre de nodes.

El servei és intencionadament passiu. Res a l'interior mou un transform ni dispara esdeveniments. Els sistemes externs —el game loop, un controlador d'IA, un reproductor de seqüències— criden AdvanceProgress a cada frame. El renderitzat el gestiona UnityRailFollowerView, un MonoBehaviour que llegeix GetSnapshot a cada actualització i aplica una posa interpolada a qualsevol transform objectiu amb orientació look-ahead opcional i suavitzat exponencial.

Com encaixa a Serenity

Game Rail viu al namespace Serenity.GameRail i segueix l'estructura per capes de la foundation. La capa de Domini defineix els value objects RailId, RailProgress, RailNodePosition i RailSnapshot, l'entitat RailPath i l'struct de configuració RailPathConfig, tots en C# pur sense dependències del motor. La capa d'Aplicació exposa IGameRailService. La capa d'Infraestructura proporciona UnityGameRailService, la implementació MonoBehaviour, i UnityRailFollowerView per aplicar el transform. La instal·lació la gestiona UnityGameRailInstaller.

Game Rail coopera amb Game Mode perquè el mode actiu pugui registrar i restablir rails als límits de fase o wave, amb el Spawner perquè els actors instanciats puguin vincular-se a un rail en crear-se, amb Game Session per a seqüències de fase i wave sobre rails, i amb sistemes de reproducció de seqüències o cinemàtiques que necessiten un progrés precís i controlat externament al llarg d'un camí de càmera o cinematogràfic.

Flux de treball pràctic

  1. Defineix els camins de rail com a structs RailPathConfig amb un RailId i un array ordenat de waypoints RailNodePosition.
  2. Crida ConfigureRail a IGameRailService durant la inicialització, típicament des de l'instal·lador o un script de configuració de nivell.
  3. Avança el progrés a cada frame cridant AdvanceProgress amb un delta escalar en temps des del teu game loop, controlador d'IA o reproductor de seqüències.
  4. Afegeix UnityRailFollowerView a qualsevol GameObject que hagi de seguir el rail; vincula el RailId objectiu i configura el mostreig d'orientació i el suavitzat a l'inspector.
  5. Crida GetSnapshot des de qualsevol altre sistema —rig de càmera, barra de progrés a la UI, disparador d'esdeveniments— per llegir l'estat immutable del rail sense acoblar-te a l'objecte que es mou.
  6. Crida ResetProgress o SetProgress des de Game Mode o el Spawner per reiniciar o saltar a un punt concret quan una fase es reinicia.

Què inclou

  • IGameRailService amb ConfigureRail, RegisterRail, AdvanceProgress, SetProgress, GetProgress, GetSnapshot i ResetProgress
  • Struct de configuració immutable RailPathConfig que combina RailId i arrays ordenats de RailNodePosition
  • Value object RailProgress normalitzat de 0 a 1 amb Advance acotat i helpers IsAtStart i IsAtEnd
  • Model de lectura immutable RailSnapshot que exposa RailId, RailProgress i NodeCount per a lectures sense acoblament
  • Identitat amb nom RailId que desacobla el registre del consum entre sistemes
  • MonoBehaviour UnityRailFollowerView amb fase d'actualització configurable, orientació look-ahead i suavitzat exponencial
  • Disseny intencionadament passiu: el progrés sempre l'impulsen sistemes externs, mai s'auto-actualitza
  • Integració amb Game Mode, Spawner i Game Session per a seqüències de fase i wave sobre rails

Quan fer-lo servir

  • Projectes de rail shooter o runner on el jugador, els enemics i la càmera necessiten compartir la mateixa posició del camí.
  • Sistemes de càmera cinematogràfica que segueixen un camí amb script controlat per un reproductor de seqüències o cinemàtiques en lloc d'un component auto-animat.
  • Dissenys de fase o wave on Game Mode o el Spawner necessita restablir o saltar a una posició concreta del rail en temps d'execució.
  • Qualsevol projecte on més d'un sistema necessiti llegir el progrés del rail sense conflictes de propietat ni referències directes entre components.

Sistemes relacionats

Fes servir Serenity quan necessitis moviment sobre rails que sigui llegible per qualsevol sistema, escrivible per un de sol i reutilitzable entre escenes, sense que un únic MonoBehaviour intenti posseir el transform, l'estat i els esdeveniments alhora.

Tornar a la pàgina principal