Capa de Persistència de Dades

Una jerarquia de ports que desacobla els contractes de desat dels backends de Unity perquè l'emmagatzematge en fitxers, PlayerPrefs i el xifratge puguin canviar sense tocar el codi del joc.

Per a què serveix aquest sistema

Tots els jocs necessiten desar dades, i tots els projectes acaben acoblant aquesta necessitat a un backend concret massa aviat. Les rutes de fitxers es dispersen pels sistemes, les claus de PlayerPrefs col·lisionen, el xifratge s'afegeix com a pedaç posterior i canviar un enfocament d'emmagatzematge per un altre es converteix en una refactorització en lloc d'un canvi de configuració.

La capa de Persistència de Serenity defineix el contracte de desat a nivell de domini i manté Unity fora d'ell. Els backends implementen ports. El codi del joc parla amb ports. El sistema de Checkpoint i Game Settings se superposen a la mateixa base sense saber quin store hi ha a sota.

El problema a Unity

Cridar directament File.WriteAllBytes o PlayerPrefs.SetString des del codi del joc funciona fins que deixa de fer-ho. El primer cop que es vol afegir xifratge, cal tocar cada punt de desat. El primer cop que el projecte s'executa en un context amb el sistema de fitxers restringit, no hi ha cap costura per injectar una alternativa. Els health checks no existeixen, de manera que els errors de persistència apareixen com a excepcions en temps d'execució en lloc de com a degradació controlada.

Les col·lisions de namespace són un altre mode de fallada silenciós. Dos sistemes que escriuen la mateixa clau de PlayerPrefs se sobreescriuen mútuament sense avisar. No hi ha separació imposada, no hi ha contracte de comprovació d'existència i no hi ha cap operació d'eliminació comuna. Cada sistema inventa les seves pròpies convencions i el projecte acumula patrons incompatibles.

Com ho aborda Serenity

Serenity defineix una jerarquia de ports sota el namespace Serenity.Persistence. IPersistenceStore és la base: porta una propietat Namespace i un mètode HealthCheckAsync que tots els backends han de satisfer. IKeyedStore l'estén amb ExistsAsync i DeleteAsync. IBlobStore afegeix I/O de stream asíncron a través de IReadOnlyBlobStore, mentre que IKeyValueStore ofereix get i set tipats a nivell de bytes per a backends lleugers. IAppendableBlobStore gestiona escenaris d'append a l'estil de log. IContentTransformer cobreix el parell Transform i InverseTransform per a pipelines de xifratge i compressió.

Dos backends concrets s'inclouen de sèrie. FileStore implementa IBlobStore i IAppendableBlobStore usant IFileWriterService per a escriptures atòmiques sobre el sistema de fitxers. UnityPlayerPrefsKeyValueStore implementa IKeyValueStore i emmagatzema els valors com a strings Base64 a PlayerPrefs sota un prefix opcional, evitant col·lisions de claus entre sistemes. Tots dos informen d'un string de namespace i responen als health checks.

Per a dades estructurades i consultables — registres amb camps, filtres i ordenació en lloc d'un blob opac — la mateixa capa guanya la família de contractes IStructuredStore, agnòstica a la tecnologia: registres amb clau, consultes de filtre/ordre/límit/recompte i upsert condicional. És el backend compartit darrere de Classificacions, GameSave/GameProgress i el logging estructurat, i és deliberadament plural en backends: clau-valor local del dispositiu, fitxers JSON llegibles, una base de dades SQLite incrustada, el teu propi servei HTTP o una connexió directa a Postgres/MySQL/MongoDB per a entorns de confiança. Un contracte, cinc llocs intercanviables on posar les dades.

Com encaixa a Serenity

Persistència segueix l'estructura per capes de Serenity. La capa de Domini conté les interfícies de port: IPersistenceStore, IKeyedStore, IReadOnlyBlobStore, IBlobStore, IAppendableBlobStore, IKeyValueStore, IContentTransformer i ISerializer. La capa d'Aplicació publica els casos d'ús PersistenceSaveObject, PersistenceLoadObject, PersistenceSaveBytes i PersistenceLoadBytes juntament amb els seus DTOs d'entrada, agrupats sota PersistenceUseCases. La capa d'Infraestructura conté FileStore al mòdul FilePersistence i UnityPlayerPrefsKeyValueStore al mòdul PlayerPrefsPersistence. La instal·lació connecta tot a través de PersistenceInstaller, FilePersistenceInstaller i PlayerPrefsPersistenceInstaller.

El sistema de Checkpoint i Game Settings consumeixen la persistència a través de les mateixes interfícies de port, de manera que són agnòstics al backend per defecte. Reemplaçar FileStore per un backend al núvol o canviar el serialitzador implica modificar un installer, no editar els sistemes del joc.

El costat estructurat viu al costat, al mòdul StructuredPersistence, amb les seves pròpies implementacions de backend darrere d'IStructuredStore — KeyValue, LocalFile (JSON amb format llegible), Sqlite (una base de dades incrustada en un fitxer, amb l'esquema creat automàticament al primer ús), i HTTP/Postgres/MySQL/MongoDB darrere dels scripting defines SERENITY_STRUCTURED_*. Cada backend de base de dades necessita DLLs de driver instal·lades a mà i fora del control de versions, així que Tools ▸ Serenity ▸ Validate ▸ Database Drivers llegeix un manifest per backend amb els paquets NuGet i fitxers d'assemblat exactes que cadascun necessita, marca quins ja estan instal·lats i només ofereix activar l'scripting define quan el conjunt complet és al seu lloc — un define mai s'encén abans que les DLLs de què depèn.

Flux de treball pràctic

  1. Triar quin backend s'ajusta a les dades objectiu: FileStore per a desats binaris i replays, UnityPlayerPrefsKeyValueStore per a ajustos lleugers, o un backend IStructuredStore per a registres consultables com classificacions i slots de desament.
  2. Registrar el backend triat a través de l'installer corresponent perquè el contenidor resolgui la implementació correcta d'IPersistenceStore.
  3. Opcionalment, encadenar un IContentTransformer per xifrar o comprimir els payloads abans que arribin al store.
  4. Fer servir els casos d'ús d'aplicació PersistenceSaveObject i PersistenceLoadObject per persistir objectes de domini sense escriure codi de serialització a mà.
  5. Cridar HealthCheckAsync en arrencar o des d'un sistema de diagnòstic per confirmar que el backend és accessible abans de la primera escriptura.
  6. Per a dades estructurades, triar una targeta de backend (dispositiu / fitxers / base de dades) a l'asset d'ajustos de la feature corresponent i, per a un backend de base de dades, obrir Database Drivers per instal·lar els paquets exactes que necessita abans d'activar el seu scripting define.
  7. Afegir un nou backend implementant les interfícies de port rellevants i registrant-les a través d'un installer personalitzat, sense necessitat de canviar el codi del joc.

Què inclou

  • Port base IPersistenceStore amb propietat Namespace i HealthCheckAsync per a tots els backends
  • IKeyedStore que afegeix ExistsAsync i DeleteAsync al contracte comú
  • IBlobStore i IReadOnlyBlobStore per a I/O binari asíncron basat en streams
  • IKeyValueStore per a get/set tipat de bytes a nivell lleuger, adequat per a backends a l'estil PlayerPrefs
  • IAppendableBlobStore per a escenaris de només append com logs i replays
  • IContentTransformer amb Transform i InverseTransform per a pipelines de xifratge i compressió
  • FileStore que implementa IBlobStore amb escriptures atòmiques a través de IFileWriterService
  • UnityPlayerPrefsKeyValueStore que emmagatzema valors Base64 a PlayerPrefs sota un prefix de clau configurable
  • Família de contractes IStructuredStore per a registres consultables, filtrables i ordenables — compartida per Classificacions, GameSave, GameProgress i el logging estructurat
  • Cinc backends estructurats intercanviables: clau-valor del dispositiu, fitxers JSON llegibles, SQLite incrustat, el teu propi servei HTTP o Postgres/MySQL/MongoDB directes
  • Finestra Database Drivers (Tools ▸ Serenity ▸ Validate ▸ Database Drivers) que llista les DLLs de driver i paquets NuGet exactes de cada backend, i bloqueja el seu scripting define fins que estiguin tots instal·lats

Quan fer-lo servir

  • Projectes que necessiten canviar el backend de desat entre plataformes sense modificar els sistemes del joc.
  • Jocs que requereixen xifratge o compressió en les dades desades i volen un únic punt de transformació.
  • Bases de codi on múltiples sistemes desen dades i necessiten separació de namespace imposada per prevenir col·lisions de claus.
  • Projectes que construeixen sobre els sistemes Checkpoint o Game Settings de Serenity, que consumeixen aquests ports directament.
  • Features que necessiten registres consultables, classificats o filtrats — classificacions, slots de desament, logs estructurats — recolzats per qualsevol cosa des d'un fitxer local fins a una base de dades real.

Sistemes relacionats

Utilitza Serenity quan vulguis contractes de persistència que sobrevisquin a qualsevol backend concret — fitxers avui, núvol demà, registres estructurats o un blob en brut — amb xifratge, health checks i seguretat de namespace ja incorporats.

Tornar a la pàgina principal