Hvordan lagre og laste spillernes fremgang i enhet

Hva du skal skape

I denne opplæringen lærer du hvordan du implementerer et enkelt system for å opprette og administrere savegames for Unity-spillene dine. Vi vil bygge rammen for a Final Fantasy-som hovedmeny som gjør det mulig for spillerne å lage nye, unike lagre filer, og å laste eksisterende. Prinsippene som er demonstrert, vil tillate deg å utvide dem til det du trenger spillet ditt. 

Ved slutten av opplæringen har du lært å:

  • lagre og last spilldata i Unity3D ved hjelp av serialisering
  • bruk statiske variabler for å vedvare data på tvers av scenendringer

Merk: Denne tilnærmingen til lagring og lasting av spilldata fungerer på alle plattformer bortsett fra webspilleren. For informasjon om lagring av spilldata i Web Player, ta en titt på de offisielle dokumentene på Unity Web Player og nettleserkommunikasjon.

La oss få seriell

Det første vi skal gjøre er å lage kode som gjør at vi serialiserer våre spilldata, det vil si, konvertere det til et format som kan lagres og senere gjenopprettes. For dette, la oss lage et C # -skript og ringe det SaveLoad. Dette skriptet håndterer alle lagrings- og lastefunksjonene. 

Vi vil referere dette skriptet fra andre skript, så la oss gjøre det til en statisk klasse ved å legge til ordet statisk mellom offentlig og klasse. La oss også fjerne : MonoBehaviour del, fordi vi ikke trenger å knytte den til en GameObject. Og siden den ikke lenger arver fra MonoBehaviour, la oss slette Start og Oppdater funksjoner. 

Den resulterende koden skal se slik ut:

bruker UnityEngine; bruker System.Collections; offentlig statisk klasse SaveLoad 

Nå skal vi legge til litt ny funksjonalitet til dette skriptet, så umiddelbart under hvor det står bruker System.Collections;, legg til følgende:

bruker System.Collections.Generic; bruker System.Runtime.Serialization.Formatters.Binary; bruker System.IO;

Den første linjen tillater oss å bruke dynamiske lister i C #, men dette er ikke nødvendig for serialisering. Den andre linjen er det som gjør at vi kan bruke operativsystemets serialiseringsfunksjoner i skriptet. I den tredje linjen, IO står for Input / Output, og er det som tillater oss å skrive til og lese fra vår datamaskin eller mobilenhet. Med andre ord lar denne linjen oss lage unike filer og deretter lese fra disse filene senere.

Vi er nå klar til å serialisere noen data!

Å lage serialiserbare klasser

Nå som vårt skript har muligheten til å serialisere, må vi sette opp noen klasser for å bli serialisert. Hvis du tenker på en grunnleggende RPG, liker du det Final Fantasy, Det gir spillere muligheten til å lage og laste forskjellige lagrede spill. Så, opprett et nytt C # -skript som heter Spillog gi det noen variabler for å holde tre objekter: a ridder, en rogue, og a veiviser. Endre koden for dette skriptet for å se slik ut:

bruker UnityEngine; bruker System.Collections; [System.Serializable] offentlig klasse Spill offentlig statisk spill nåværende; offentlig karakter ridder; offentlig karakter skurk; offentlig tegnveiviser; offentlig spill () knight = nytt tegn (); rogue = nytt tegn (); veiviser = nytt tegn (); 

De [System.Serializable] linje forteller Unity at dette skriptet kan være serialisert-med andre ord, at vi kan lagre alle variablene i dette skriptet. Kul! Ifølge de offisielle dokumentene kan Unity serialisere følgende typer:

  • Alle grunnleggende datatyper (som int, string, flyte, og bool).
  • Noen innebygde typer (inkludert Vektor2, Vector3, Vector4, quaternion, Matrix4x4, Farge, rect, og LayerMask).
  • Alle klasser som arver fra UnityEngine.Object (gjelder også GameObject, Komponent, MonoBehavior, Texture2D, og AnimationClip).
  • enums.
  • Arrayer og lister med serielliserbar type.

Den første variabelen, nåværende, er en statisk referanse til a Spill forekomst. Når vi lager eller laster et spill, skal vi sette denne statiske variabelen til den aktuelle spillinstansen, slik at vi kan referere til "nåværende spill" hvor som helst i prosjektet. Ved å bruke statiske variabler og funksjoner trenger vi ikke å bruke en gameObject's GetComponent () funksjon. Praktisk! 

Legg merke til at det refererer til noe som heter a Karakter? Vi har ikke det ennå, så la oss lage et nytt skript for å huse denne klassen, og ring det Karakter:

bruker UnityEngine; bruker System.Collections; [System.Serializable] offentlig klasse Tegn public string name; offentlig karakter () this.name = ""; 

Du lurer kanskje på hvorfor vi trengte en helt ny klasse hvis vi bare lagrer en strengvariabel. Faktisk kan vi bare erstatte Karakter i Spill Skript å bruke string i stedet. Men jeg vil vise deg hvor dypt dette kaninhullet kan gå: du kan lagre og laste klasser som refererer til andre klasser, og så videre, så lenge som hver klasse er serialiserbar

Nå som våre klasser er satt opp for å bli lagret og lastet, la oss hoppe tilbake til vår SaveLoad skript og legg til evnen til å lagre spill.

Lagre spillets tilstand

En "Last spill" -meny viser vanligvis en liste over lagrede spill, så la oss lage en Liste av type Spill og ring det savedGames. Gjør det til en statisk liste, slik at det bare er en liste over lagrede spill i prosjektet. Koden skal se slik ut:

bruker UnityEngine; bruker System.Collections; bruker System.Collections.Generic; bruker System.Runtime.Serialization.Formatters.Binary; bruker System.IO; offentlig statisk klasse SaveLoad offentlig statisk liste savedGames = ny liste(); 

Deretter la oss lage en ny statisk funksjon for å lagre et spill:

 offentlig statisk tomrom Lagre () savedGames.Add (Game.current); BinaryFormatter bf = ny BinaryFormatter (); FileStream-fil = File.Create (Application.persistentDataPath + "/savedGames.gd"); bf.Serialize (fil, SaveLoad.savedGames); file.Close ();  

Linje 2 legger til vårt nåværende spill til vår liste over lagrede spill. Den listen er hva vi skal serialisere. For å gjøre det, må vi først opprette en ny BinaryFormatter, som vil håndtere serialiseringsarbeidet. Dette er hva Linje 3 gjør.

I linje 4 lager vi en Filestream, som egentlig er en vei til en ny fil som vi kan sende data også, som fisk som svømmer nedstrøms i en elv. Vi bruker File.Create () å opprette en ny fil på stedet vi sender inn som parameter. Praktisk har Unity en innebygd plassering for å lagre våre spillfiler (hvilke oppdateringer automatisk basert på hvilken plattform spillet ditt er bygget til) som vi kan referere til ved hjelp av Application.persistentDataPath

Siden vi lager en ny fil, kan vi imidlertid ikke bare si hvor filen er, vi må også dekke denne banen med navnet på selve filen selv. Det er to deler til denne filen:

  1. filnavnet
  2. filtypen

Vi skal bruke savedGames for filnavnet, og vi bruker en egendefinert datatype gd (for "spilldata") for filtypen. Vårt resultat er en spillfil som heter savedGames.gd på stedet satt av Application.persistentDataPath. (I fremtiden kan du lagre andre typer ting til denne datatypen, for eksempel kan du lagre brukerens valginnstillinger som options.gd.)

Merk: Du kan gjøre filtypen alt du vil ha. For eksempel bruker Elder Scrolls-serien .ESM som sin filtype. Du kunne like sagt sagt savedGames.baconAndGravy.

I linje 5 ringer vi på serial funksjonaliteten til BinaryFormatter å redde vår savedGames liste til vår nye fil. Etter det har vi lukk filen vi opprettet, på linje 6. 

Badda bing, badda boom. Våre spill er lagret.

Legger inn en spillstat

I Lagre funksjon, serialiserte vi vår liste over lagrede spill på et bestemt sted. Omvendt bør koden for å laste inn spillene våre se slik ut:

 offentlig statisk tomrom Load () if (File.Exists (Application.persistentDataPath + "/savedGames.gd")) BinaryFormatter bf = new BinaryFormatter (); FileStream file = File.Open (Application.persistentDataPath + "/savedGames.gd", FileMode.Open); SaveLoad.savedGames = (Liste) Bf.Deserialize (fil); file.Close (); 

I linje 2 kontrollerer vi om en lagret spillfil eksisterer. (Hvis det ikke gjøres, vil det ikke være noe å laste, åpenbart.) I Linje 3 oppretter vi en BinaryFormatter På samme måte som vi gjorde i Lagre funksjon. I linje 4 lager vi en Filestream-men denne gangen svømmer fisken oppstrøms fra filen. Dermed bruker vi Fil.Åpen, og peker til hvor vår savedGames.gd eksisterer ved å bruke det samme Application.persistentDataPath string. 

Linje 5 er litt tett, så la oss pakke ut det: 

  • De bf.Deserialize (fil) anrop finner filen på stedet vi angitt ovenfor og deserialiserer den. 
  • Vi kan ikke bare spytte binær på Unity og forventer at det skal fungere, men det er vi også konverter (eller cast) vår deserialiserte fil til datatypen vi vil ha den, som i dette tilfellet er a Liste av typen Spill. 
  • Vi setter da listen som vår liste over lagrede spill. 

Til slutt, i linje 6 lukker vi den filen på samme måte som vi gjorde i Lagre funksjon. 

Merk: Datatypen som du kaster de deserialiserte dataene, kan endres avhengig av hva du trenger den til å være. For eksempel, Player.lives = (int) bf.Dererialize (fil);.

Konklusjon

Våre SaveLoad Skriptet er nå fullført, og skal se slik ut:

bruker UnityEngine; bruker System.Collections; bruker System.Collections.Generic; bruker System.Runtime.Serialization.Formatters.Binary; bruker System.IO; offentlig statisk klasse SaveLoad offentlig statisk liste savedGames = ny liste(); // det er statisk, slik at vi kan ringe det fra hvor som helst offentlig statisk tomt Lagre () SaveLoad.savedGames.Add (Game.current); BinaryFormatter bf = ny BinaryFormatter (); //Application.persistentDataPath er en streng, så hvis du ønsket at du kan sette det inn i debug.log hvis du vil vite hvor lagre spill er plassert FileStream file = File.Create (Application.persistentDataPath + "/savedGames.gd"); // du kan kalle det alt du vil bf.Serialize (file, SaveLoad.savedGames); file.Close ();  statisk statisk tomrom Load () if (File.Exists (Application.persistentDataPath + "/savedGames.gd")) BinaryFormatter bf = new BinaryFormatter (); FileStream file = File.Open (Application.persistentDataPath + "/savedGames.gd", FileMode.Open); SaveLoad.savedGames = (Liste) Bf.Deserialize (fil); file.Close ();  

Det er grunnleggende om lagring og lasting i Unity. I den vedlagte prosjektfilen finner du noen andre skript som viser hvordan jeg håndterer å ringe disse funksjonene og hvordan jeg viser dataene ved hjelp av Unitys GUI.

Hvis du trenger en start med spillutviklingen, kan du prøve Unity3D-malene som er tilgjengelige på Envato Market.