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 å:
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.
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!
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 Spill
og 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:
int
, string
, flyte
, og bool
).Vektor2
, Vector3
, Vector4
, quaternion
, Matrix4x4
, Farge
, rect
, og LayerMask
).UnityEngine.Object
(gjelder også GameObject
, Komponent
, MonoBehavior
, Texture2D
, og AnimationClip
).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.
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 listesavedGames = 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:
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.
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:
bf.Deserialize (fil)
anrop finner filen på stedet vi angitt ovenfor og deserialiserer den. Liste
av typen 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);
.
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 listesavedGames = 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.