Comment enregistrer et charger le progrès de vos joueurs dans Unity

Ce que vous allez créer

Dans ce didacticiel, vous apprendrez à mettre en œuvre un système simple pour créer et gérer des sauvegardes pour vos jeux Unity. Nous allons construire le cadre pour un Final Fantasy-comme le menu principal qui permet aux joueurs de créer de nouveaux fichiers de sauvegarde uniques et de charger ceux qui existent déjà. Les principes démontrés vous permettront de les étendre à tous les besoins de votre jeu.. 

À la fin du tutoriel, vous aurez appris à:

  • enregistrer et charger des données de jeu dans Unity3D à l'aide de la sérialisation
  • utiliser des variables statiques pour conserver les données lors des changements de scène

Remarque: cette approche de sauvegarde et de chargement des données de jeu fonctionne sur toutes les plateformes. sauf pour le Web Player. Pour plus d'informations sur la sauvegarde des données de jeu dans Web Player, consultez la documentation officielle sur Unity Web Player et la communication avec le navigateur..

Passons en série

La première chose que nous allons faire est de créer un code nous permettant de sérialiser nos données de jeu, c'est-à-dire de le convertir en un format pouvant être sauvegardé puis restauré. Pour cela, créons un script C # et appelons-le Sauvegarder charger. Ce script va gérer toutes les fonctionnalités de sauvegarde et de chargement. 

Nous allons référencer ce script à partir d'autres scripts, alors faisons-en une classe statique en ajoutant le mot statique entre Publique et classe. Enlevons aussi le : MonoBehaviour partie, parce que nous n'avons pas besoin de l'attacher à un GameObject. Et comme il n'hérite plus de MonoBehaviour, effaçons le Début et Mettre à jour les fonctions. 

Le code résultant devrait ressembler à ceci:

utiliser UnityEngine; using System.Collections; classe statique publique SaveLoad 

Maintenant, nous allons vouloir ajouter de nouvelles fonctionnalités à ce script, donc immédiatement sous où il est dit using System.Collections;, ajoutez ce qui suit:

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

La première ligne nous permet d'utiliser des listes dynamiques en C #, mais cela n'est pas nécessaire pour la sérialisation. La deuxième ligne est ce qui nous permet d'utiliser les fonctionnalités de sérialisation du système d'exploitation dans le script. En troisième ligne, IO représente Entrée sortie, et c’est ce qui nous permet d’écrire et de lire à partir de notre ordinateur ou de notre appareil mobile. En d’autres termes, cette ligne nous permet de créer des fichiers uniques, puis de les lire plus tard..

Nous sommes maintenant prêts à sérialiser certaines données!

Faire des classes sérialisables

Maintenant que notre script a la capacité de sérialiser, nous allons devoir configurer certaines classes pour les sérialiser. Si vous pensez à un RPG de base, comme Final Fantasy, il offre aux joueurs la possibilité de créer et de charger différentes parties sauvegardées. Alors, créez un nouveau script C # appelé Jeuet donnez-lui des variables pour contenir trois objets: un Chevalier, une coquin, et un sorcier. Changez le code de ce script pour qu'il ressemble à ceci:

utiliser UnityEngine; using System.Collections; [System.Serializable] public class Game public statique Game actuel; personnage public knight; public caractère voyou; assistant de personnage public; jeu public () chevalier = nouveau personnage (); voyou = nouveau personnage (); assistant = nouveau personnage (); 

le [System.Serializable] La ligne indique à Unity que ce script peut être sérialisé-autrement dit, nous pouvons sauvegarder toutes les variables de ce script. Cool! Selon la documentation officielle, Unity peut sérialiser les types suivants:

  • Tous les types de données de base (comme int, chaîne, flotte, et bool).
  • Certains types intégrés (y compris Vecteur2, Vecteur3, Vecteur4, Quaternion, Matrix4x4, Couleur, Rect, et Masque de calque).
  • Toutes les classes héritant de UnityEngine.Object (comprenant GameObject, Composant, MonoBehavior, Texture2D, et AnimationClip).
  • Enums.
  • Tableaux et listes d'un type sérialisable.

La première variable, actuel, est une référence statique à un Jeu exemple. Lorsque nous créons ou chargeons un jeu, nous allons définir cette variable statique sur cette instance de jeu particulière afin de pouvoir référencer le "jeu actuel" à partir de n'importe où dans le projet. En utilisant des variables et des fonctions statiques, nous n’avons pas à utiliser un gameObjectde GetComponent () une fonction. Pratique! 

Notez qu'il fait référence à quelque chose appelé un Personnage? Nous ne l'avons pas encore, alors créons un nouveau script pour héberger cette classe et appelons-le Personnage:

utiliser UnityEngine; using System.Collections; [System.Serializable] public class Caractère nom de chaîne publique; caractère public () this.name = ""; 

Vous vous demandez peut-être pourquoi nous avions besoin d'une toute nouvelle classe si nous ne stockons qu'une variable de chaîne. En effet, nous pourrions simplement remplacer Personnage dans le Jeu script à utiliser chaîne au lieu. Mais je veux vous montrer à quelle profondeur ce trou de lapin peut aller: vous pouvez enregistrer et charger des classes qui référencent d’autres classes, et ainsi de suite, à condition que chaque classe est sérialisable

Maintenant que nos classes sont configurées pour être sauvegardées et chargées, revenons à notre Sauvegarder charger script et ajouter la possibilité de sauvegarder des jeux.

Sauvegarder l'état d'un jeu

Un menu "Charger la partie" affiche généralement une liste des parties sauvegardées. Nous allons donc créer une liste de type Jeu et l'appelle SavedGames. En faire un Liste statique, de sorte qu'il n'y a qu'une seule liste de parties sauvegardées dans notre projet. Le code devrait ressembler à ceci:

utiliser UnityEngine; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization.Formatters.Binary; using System.IO; classe statique publique SaveLoad liste statique publique savedGames = nouvelle liste(); 

Ensuite, créons une nouvelle fonction statique pour sauvegarder un jeu:

 public statique void Save () savedGames.Add (Game.current); BinaryFormatter bf = new BinaryFormatter (); FileStream file = File.Create (Application.persistentDataPath + "/savedGames.gd"); bf.Serialize (fichier, SaveLoad.savedGames); file.Close ();  

Line 2 ajoute notre jeu actuel à notre liste de jeux sauvegardés. Cette liste est ce que nous allons sérialiser. Pour ce faire, nous devons d’abord créer un nouveau BinaryFormatter, qui gérera le travail de sérialisation. C'est ce que fait la ligne 3.

Dans la ligne 4, nous créons un FileStream, ce qui est essentiellement une voie vers un nouveau fichier vers lequel nous pouvons également envoyer des données, comme des poissons nageant en aval dans une rivière. Nous utilisons File.Create () pour créer un nouveau fichier à l’emplacement que nous passons en tant que paramètre. De manière pratique, Unity a un emplacement intégré pour stocker nos fichiers de jeu (qui sont mis à jour automatiquement en fonction de la plate-forme sur laquelle votre jeu est construit), que nous pouvons référencer à l'aide de Application.persistentDataPath

Étant donné que nous créons un nouveau fichier, nous ne pouvons pas simplement dire où se trouve le fichier, nous devons également fermer ce chemin avec le nom du fichier lui-même. Il y a deux parties dans ce fichier:

  1. le nom du fichier
  2. le type de fichier

Nous allons utiliser SavedGames pour le nom du fichier, et nous utiliserons un type de données personnalisé gd (pour "données de jeu") pour le type de fichier. Notre résultat est un fichier de jeu appelé savedGames.gd à l'emplacement fixé par Application.persistentDataPath. (A l'avenir, vous pourrez enregistrer d'autres types d'éléments dans ce type de données. Par exemple, vous pouvez enregistrer les paramètres d'options des utilisateurs en tant que options.gd.)

Remarque: Vous pouvez faire le type de fichier que vous voulez. Par exemple, la série Elder Scrolls utilise .esm comme son type de fichier. Vous auriez pu dire aussi facilement SavedGames.baconAndGravy.

Sur la ligne 5, nous appelons le Sérialiser fonctionnalité de la BinaryFormatter pour sauver notre SavedGames liste à notre nouveau fichier. Après cela, nous avons la fermeture du fichier que nous avons créé, dans la ligne 6. 

Badda Bing, Badda Boom. Nos jeux sont sauvés.

Chargement de l'état d'un jeu

dans le sauvegarder fonction, nous avons sérialisé notre liste de parties sauvegardées à un emplacement spécifique. Inversement, le code pour charger nos jeux devrait ressembler à ceci:

 public static void 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 (fichier); file.Close (); 

Dans la ligne 2, nous vérifions si un fichier de jeu enregistré existe. (Sinon, il n'y aura évidemment rien à charger.) Dans la ligne 3, nous créons un BinaryFormatter de la même manière que nous avons fait dans le sauvegarder une fonction. Dans la ligne 4, nous créons un FileStream-mais cette fois, nos poissons nagent en amont du fichier. Ainsi, nous utilisons Fichier.Ouvrir, et pointez là où notre savedGames.gd existe en utilisant le même Application.persistentDataPath chaîne. 

La ligne 5 est un peu dense, alors décompresons-la: 

  • le bf.Deserialize (fichier) L'appel trouve le fichier à l'emplacement spécifié ci-dessus et le désérialise.. 
  • Nous ne pouvons pas simplement cracher binaire à Unity et nous attendre à ce qu’il fonctionne, cependant, nous convertir (ou convertir) notre fichier désérialisé au type de données que nous souhaitons, qui est dans ce cas un liste de type Game. 
  • Nous avons ensuite défini cette liste comme notre liste de jeux sauvegardés. 

Enfin, à la ligne 6, nous fermons ce fichier comme nous l’avons fait dans le sauvegarder une fonction. 

Remarque: Le type de données vers lequel vous transcrivez les données désérialisées peut changer en fonction de vos besoins. Par exemple, Player.lives = (int) bf.Deserialize (fichier);.

Conclusion

Notre Sauvegarder charger le script est maintenant terminé et devrait ressembler à ceci:

utiliser UnityEngine; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization.Formatters.Binary; using System.IO; classe statique publique SaveLoad liste statique publique savedGames = nouvelle liste(); // c'est statique afin que nous puissions l'appeler de n'importe où public static statique void Save () SaveLoad.savedGames.Add (Game.current); BinaryFormatter bf = new BinaryFormatter (); //Application.persistentDataPath est une chaîne. Si vous le souhaitez, vous pouvez l'insérer dans debug.log si vous souhaitez savoir où se trouvent les sauvegardes. FileStream file = File.Create (Application.persistentDataPath + "/savedGames.gd"); // tu peux l'appeler comme tu veux bf.Serialize (file, SaveLoad.savedGames); file.Close ();  public static void 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 (fichier); file.Close ();  

Ce sont les bases de la sauvegarde et du chargement dans Unity. Dans le fichier de projet joint, vous trouverez d'autres scripts qui montrent comment je gère l'appel de ces fonctions et comment afficher les données à l'aide de l'interface graphique de Unity..

Si vous avez besoin d'une longueur d'avance avec le développement de votre jeu, essayez les modèles Unity3D disponibles sur Envato Market..