Quantcast
Channel: Answers by "ThePersister"
Viewing all articles
Browse latest Browse all 99

Answer by ThePersister

$
0
0
Hey @Furcifer-bellator !! Thank you for the direct question, I'm flattered :) I created a Save System Example for you based on this other post: http://answers.unity3d.com/questions/610893/how-do-i-save-a-custom-class-of-variables-to-playe.html @iwaldrop showed a beautiful example for a Serializer that can be used to save data. I created an example that applies this Serializer with some slight adjustments. **Download the package here!** https://www.dropbox.com/s/tmzf6vtc73wloom/SaveLoadExample.unitypackage?dl=0 **Here's the visual preview:** ![Preview of the SaveSystemExample][1] **Here's the Code (Explained at bottom of the post):** **Serializer:** using System; using System.IO; using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization.Formatters.Binary; public class Serializer { private const string m_fileExtension = ".dat"; private const string m_prefix = "SaveSystemExample_"; private static string _getFullStorePath(string filename) { return Application.persistentDataPath + "/" + m_prefix + filename + m_fileExtension; } public static T Load(string filename) where T : class { if (File.Exists(_getFullStorePath(filename))) { try { using (Stream stream = File.OpenRead(_getFullStorePath(filename))) { BinaryFormatter formatter = new BinaryFormatter(); return formatter.Deserialize(stream) as T; } } catch (Exception e) { Debug.Log(e.Message); } } return default(T); } public static void Save(string filename, T data) where T : class { using (Stream stream = File.OpenWrite(_getFullStorePath(filename))) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, data); } } } **SaveSlot:** using UnityEngine; using System.Collections; public class SaveSlot : MonoBehaviour { public string m_boundFileName = "SaveSlotX"; } **Character (Example class to save, that fits your context):** using UnityEngine; using System; [Serializable] public class Character { [Header("Meta")] public string m_name = "Lex"; [Header("Attributes")] [Range(0f, 10f)] public int m_strength = 7; [Range(0f, 10f)] public int m_intelligence = 9, m_agility = 8, m_endurance = 7, m_luck = 10; [Header("Weapon")] public Weapon m_currentWeapon = new Weapon("Dragonslayer Blade", 9001f); [Header("Armor")] public Armor m_currentArmor = new Armor("Dragonscale Armor", 0.4f); } [Serializable] public class Weapon { public string m_name; public float m_dps; // Damage per second. public Weapon(string name, float dps) { m_name = name; m_dps = dps; } } [Serializable] public class Armor { public string m_name; [Range(0f,1f)] public float m_durability01, m_damageReduction01; public Armor(string name, float damageReduction01) { m_name = name; m_damageReduction01 = Mathf.Clamp01(damageReduction01); m_durability01 = 1.0f; // Starts at full durability. } } **SaveSystem (Saving, Loading and a bit of UI, cut away what you don't need):** using UnityEngine; using System.Collections; using UnityEngine.UI; using System.Linq; public class SaveSystem : MonoBehaviour { public ToggleGroup m_saveSlotsGroup; public Character m_currentCharacter; void Start() { // Load existing saveSlots' data. SaveSlot[] saveSlots = m_saveSlotsGroup.GetComponentsInChildren(); foreach (SaveSlot saveSlot in saveSlots) { LoadSaveSlot(saveSlot); } } public void Save() { SaveSlot selectedSaveSlot = _getSelectedSaveSlot(); Serializer.Save(selectedSaveSlot.m_boundFileName, m_currentCharacter); _updateCharacterText(selectedSaveSlot); } public void Load() { SaveSlot selectedSaveSlot = _getSelectedSaveSlot(); LoadSaveSlot(selectedSaveSlot); } private void LoadSaveSlot(SaveSlot saveSlot) { m_currentCharacter = Serializer.Load(saveSlot.m_boundFileName); if (m_currentCharacter != null) { // Succesfully loaded character: _updateCharacterText(saveSlot); } } private void _updateCharacterText( SaveSlot saveSlot ) { // Visual update for the button Label. saveSlot.GetComponentInChildren().text = m_currentCharacter.m_name; } private SaveSlot _getSelectedSaveSlot() { if (m_saveSlotsGroup.AnyTogglesOn()) { Toggle activeToggle = m_saveSlotsGroup.ActiveToggles().First(); SaveSlot selectedSaveSlot = activeToggle.GetComponent(); if (selectedSaveSlot == null) { throw new System.NullReferenceException("SaveSlot was null, check whether the active toggle had a SaveSlot script on it"); } else { return selectedSaveSlot; } } else { throw new System.NullReferenceException("To do anything with SaveSlots, you'll have to select one first."); } } } Basically: 1. The **Serializer class** is the main code you need for loading and saving, everything else is just data / filename binding. 2. The **Character class** is an example of a class you could save. 3. The **SaveSlot class** just hold a filename string that's used to save and load at a specific location. 4. The **SaveSystem** has a **ToggleGroup** reference and gets the **selected SaveSlot** from it (the Toggles each have a SaveSlot component), then it gets the filename defined in the SaveSlot and uses that to **Load and/or Save the current Character** data, lastly updates the text of the toggles for better visual feedback! 5. The two buttons shown in the preview call the Load and Save methods in the SaveSystem to trigger a Save or Load using the selected SaveSlot. I hope all of that made sense! Thank you for another cool question, I enjoyed making this one and I might need something similar myself in the future, so thank you! ;) If this helped, please accept the answer, it'd be much appreciated! Best of luck! Cheers, ThePersister [1]: /storage/temp/82421-savesystemexamplepreview.png

Viewing all articles
Browse latest Browse all 99

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>