Search Unity

Saving character selection to a binary file? (C#)

Discussion in 'Scripting' started by LadyAth, Oct 19, 2014.

  1. LadyAth

    LadyAth

    Joined:
    Jan 17, 2014
    Posts:
    158
    I'd like to change my character selection to use a binary file with serialization instead of playerprefs, but a newbie when it comes to coding. The code below works, but it seems inefficient (even to me) and I'd love a better way. The setup is as follows:

    Player can start a new game or continue an old one (not managed to code that yet) and when selecting a new game, can choose from one of four characters. The character stats are the same for each character, but they will eventually have a unique ability just to make it a little special. The main menu and character selection are on different scenes and the below is from the character selection where the player clicks on a button (using uGUI) and selects OK to continue:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using UnityEngine.Events;
    4. using System.Collections;
    5.  
    6. public class SelectMyCharacter : MonoBehaviour {
    7.  
    8. public void ActiveCat(){
    9.     SpawnMyCharacter.characterSelected = 0;
    10. }
    11. public void ActiveDog(){
    12.     SpawnMyCharacter.characterSelected = 1;
    13. }
    14. public void ActiveOwl(){
    15.     SpawnMyCharacter.characterSelected = 2;
    16. }
    17. public void ActiveTurtle(){
    18.     SpawnMyCharacter.characterSelected = 3;
    19. }
    20.  
    21. public void SetOk(){
    22.     PlayerPrefs.DeleteAll();
    23.     PlayerPrefs.SetInt ("PLAYERLEVEL", 1);
    24.     PlayerPrefs.SetInt ("ATTACK", 10);
    25.     PlayerPrefs.SetInt ("DEFENCE", 10);
    26.     PlayerPrefs.SetInt ("POWER", 10);
    27.     PlayerPrefs.SetInt ("CURHEALTH", 20);
    28.     PlayerPrefs.SetInt ("MAXHEALTH", 20);
    29.     PlayerPrefs.SetString ("EXISTINGGAME", "No");
    30.     PlayerPrefs.SetInt ("SELECTEDCHARACTER", SpawnMyCharacter.characterSelected);
    31.     Application.LoadLevel ("Village");
    32. }
    33.  
    34. public void SetCancel(){
    35.     PlayerPrefs.DeleteKey ("SELECTEDCHARACTER");
    36.     Application.LoadLevel ("MainMenu");
    37. }
    38. }


    The scene jumps to 'Village' where the selected character is spawned with the following code:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class SpawnMyCharacter : MonoBehaviour {
    5. public static int characterSelected;
    6. public GameObject catPlayerCharacter;
    7. public GameObject dogPlayerCharacter;
    8. public GameObject owlPlayerCharacter;
    9. public GameObject turtlePlayerCharacter;
    10.  
    11.     void Start () {
    12.         if(PlayerPrefs.HasKey("EXISTINGGAME")) {
    13.             if(PlayerPrefs.GetString("EXISTINGGAME") != "Yes"){
    14.         characterSelected = PlayerPrefs.GetInt("SELECTEDCHARACTER");
    15.         Debug.Log(characterSelected);
    16.         if(characterSelected == 0){
    17.             Instantiate(catPlayerCharacter, this.transform.position, Quaternion.identity);
    18.         } else if(characterSelected == 1) {
    19.             Instantiate(dogPlayerCharacter, this.transform.position, Quaternion.identity);
    20.         } else if(characterSelected == 2) {
    21.             Instantiate(owlPlayerCharacter, this.transform.position, Quaternion.identity);
    22.         } else if(characterSelected == 3) {
    23.             Instantiate(turtlePlayerCharacter, this.transform.position, Quaternion.identity);
    24.         }
    25.         PlayerPrefs.SetString ("EXISTINGGAME", "Yes");
    26.         }
    27.         else
    28.         {
    29.                 Debug.Log ("This is not a new game.");
    30.         }
    31.     }
    32.     }
    33. }
    34.  

    I have a game manager object that I've started to add the serialization to (thanks the Unity Live Training on the topic), but not sure how I can bring the character selection into this:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System;
    4. using System.Runtime.Serialization.Formatters.Binary;
    5. using System.IO;
    6.  
    7. public class GameManager : MonoBehaviour
    8. {
    9.     public static GameManager gamecontrol;  
    10.  
    11.     public string selectedchar;
    12.     public float curhealth;
    13.     public float maxhealth;
    14.     public float xp;
    15.     public float pclevel;
    16.     public float attack;
    17.     public float defence;
    18.     public float power;
    19.  
    20.     void Awake () {
    21.         if (gamecontrol == null) {
    22.             DontDestroyOnLoad (gameObject);
    23.             gamecontrol = this;
    24.         }
    25.         else if(gamecontrol != this)
    26.         {
    27.             Destroy (gameObject);
    28.         }
    29.     }
    30.    
    31.     public void Save()
    32.     {
    33.         BinaryFormatter bf = new BinaryFormatter ();
    34.         FileStream file = File.Create (Application.persistentDataPath + "/LHplayerInfo.dat");
    35.  
    36.         PlayerData data = new PlayerData ();
    37.         data.selectedchar = selectedchar;
    38.         data.curhealth = curhealth;
    39.         data.maxhealth = maxhealth;
    40.         data.xp = xp;
    41.         data.pclevel = pclevel;
    42.         data.attack = attack;
    43.         data.defence = defence;
    44.         data.power = power;
    45.  
    46.         bf.Serialize (file, data);
    47.         file.Close();
    48.     }
    49.  
    50.     public void Load()
    51.     {
    52.         if (File.Exists (Application.persistentDataPath + "/LHplayerInfo.dat"))
    53.         {
    54.             BinaryFormatter bf = new BinaryFormatter();
    55.             FileStream file = File.Open(Application.persistentDataPath + "/LHplayerInfo.dat", FileMode.Open);
    56.             PlayerData data = (PlayerData)bf.Deserialize(file);
    57.             file.Close();
    58.  
    59.             selectedchar = data.selectedchar;
    60.             curhealth = data.curhealth;
    61.             maxhealth = data.maxhealth;
    62.             xp = data.xp;
    63.             pclevel = data.pclevel;
    64.             attack = data.attack;
    65.             defence = data.defence;
    66.             power = data.power;
    67.     }
    68. }
    69.  
    70.  
    71. [Serializable]
    72. class PlayerData
    73. {
    74.     public string selectedchar;
    75.     public float curhealth;
    76.     public float maxhealth;
    77.     public float xp;
    78.     public float pclevel;
    79.     public float attack;
    80.     public float defence;
    81.     public float power;
    82. }

    So basically, I want to avoid playerprefs and use a binary file for as much saving as possible. Unfortunately I am stuck on how to change the character selection. Any other advice on how to handle the character stats better would also be appreciated.
     
  2. ZO5KmUG6R

    ZO5KmUG6R

    Joined:
    Jul 15, 2010
    Posts:
    490
  3. LadyAth

    LadyAth

    Joined:
    Jan 17, 2014
    Posts:
    158
    Thanks for that, but the problem for me is not the storing of info such as health, but rather character selection and what the active selected character would be. The information currently sits shared between SelectMyCharacter.cs and SpawnMyCharacter.cs and I need to (I would think) bring it together with what I have added in GameManager.cs

    But I am curious why you are converting the information to int in your example? Is there a reason why I should not be using floats for it?
     
  4. ZO5KmUG6R

    ZO5KmUG6R

    Joined:
    Jul 15, 2010
    Posts:
    490
    Because in the case of that script they would never be a 0.1 or 0.2 etc. Therefore Int32 is the most suitable data type .

    You can use the same concept for your information such as health etc. with binary this way.

    You could simply write character profiles like *.profile or something like that, and write the needed data using the binarywriter, then just read it back in the same order
     
  5. LadyAth

    LadyAth

    Joined:
    Jan 17, 2014
    Posts:
    158
    Ok, so what you suggest is that I save the character selection in the same way but just with a different file ext - sounds good! But how would I combine the information from the two files? For instance, that Owl was selected + whatever the latest stats/health/xp so that when the character is spawned, it has all the relevant information linked?
     
  6. ZO5KmUG6R

    ZO5KmUG6R

    Joined:
    Jul 15, 2010
    Posts:
    490
    You could load them into a structure

    struct Character{
    public string name;
    public float health;
    }

    Then when loading

    Character myChar = new Character();
    myChar.health = 1;

    You could have multiple character structures initialized and mix and match data from them
     
  7. LadyAth

    LadyAth

    Joined:
    Jan 17, 2014
    Posts:
    158
    *eyes glaze over* hehe I think I have more reading to do... but thank you for pointing me in the right direction! I'll get onto learning more about structures and how to work with it. Much appreciated :D