Search Unity

Looking to get a second opinion on storing values.

Discussion in 'Scripting' started by Jtoomer, Feb 7, 2017.

  1. Jtoomer

    Jtoomer

    Joined:
    Jan 30, 2017
    Posts:
    38
    So in the game that I am making here is the system that I have planned.

    A "LoadoutManager" script sends information forward to the "StatsManager" script which stores values for each weapon and piece of gear which is then read by the scripts on the player gameobject to determine textures and stats and whatnot. Now with the loadout manager, I am not entirely sure how to create a suitable format to store all the data for each weapon and piece of gear, this needs to store things like descriptions to be displayed by the UI and the stats/name/etc.

    Any recommendations?
     
  2. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    JSON or XML is my suggestion. You could then easily write a weapon/gear editor program separate from your Unity project to create/edit these weapons. You would just implement a single data storage class for reading in the XML or JSON file and copy it over to your editor program and use that to read/write the file.

    Its pretty easy to write a simple tool like that in Visual Studio
     
  3. jmgek

    jmgek

    Joined:
    Dec 9, 2012
    Posts:
    177
    takatok likes this.
  4. Jtoomer

    Jtoomer

    Joined:
    Jan 30, 2017
    Posts:
    38
    Thanks, I will look into it. I was looking for literally any solution other than "Just have like 50 variables per weapon in one class".

    I will consider both options and see which will be the best to incorporate.
     
  5. Jtoomer

    Jtoomer

    Joined:
    Jan 30, 2017
    Posts:
    38
    Alright, where would I start? I don't exactly have any experience with making something like that.

    EDIT: I would prefer XML as I am coding in C# and would prefer not to need a specific class to be the only one in JavaScript
     
    Last edited: Feb 8, 2017
  6. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Here is a generic XML Loader/Saver class. In Unity you would create this file and not attach it to anything. In your editor project you could just have it as a class file
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Xml;
    3. using System.Xml.Serialization;
    4. using System.IO;
    5.  
    6. public static class XMLOP {
    7.  
    8.     public static void Serialize(object item, string path)
    9.     {
    10.         XmlSerializer serializer = new XmlSerializer(item.GetType());
    11.         StreamWriter writer = new StreamWriter(path);
    12.         serializer.Serialize(writer.BaseStream, item);
    13.         writer.Close();
    14.     }
    15.  
    16.     public static T Deserialize<T>(string path)
    17.     {
    18.         XmlSerializer serializer = new XmlSerializer(typeof(T));
    19.         StreamReader reader = new StreamReader(path);
    20.         T item = (T)serializer.Deserialize(reader.BaseStream);
    21.         reader.Close();
    22.         return item;
    23.     }
    24. }
    25.  

    Here is how you could create a specific data class. I've included a few headers to show you how you can customize the tags in the actual xml file itself. Note in the class it will serialize everything that is public, if you had any private fields they would be skipped. I included a sample of having a having a field be an array of a second class. This class is also just in its own file in Unity, not on a GameObject:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Xml;
    3. using System.Xml.Serialization;
    4. using System.Collections.Generic;
    5.  
    6. [XmlRoot("RootName")]
    7. public class XMLData {
    8.  
    9.     // Make all the data you want in the XML file
    10.     // Public Fields
    11.     public string someString;
    12.     public Vector3 myVector;
    13.     [XmlArray("ArrayName"), XmlArrayItem("ArrayItemName")]
    14.     public SomeOtherClass[] someOtherClass;
    15.  
    16.     // this function will always look like this
    17.     public void Save(string path)
    18.     {
    19.         XMLOP.Serialize(this, path);
    20.     }
    21.  
    22.     // You need to write this function yourself to populate
    23.     // the data
    24.     public void Load(string path)
    25.     {
    26.         XMLData info =  XMLOP.Deserialize<XMLData>(path);
    27.         this.someString = info.someString;
    28.         this.myVector = info.myVector;
    29.         this.someOtherClass = new SomeOtherClass[info.someOtherClass.Length];
    30.         for (int i = 0; i < someOtherClass.Length; i++)
    31.             this.someOtherClass[i] = info.someOtherClass[i];
    32.     }
    33.  
    34. }
    35.  
    36. public class SomeOtherClass
    37. {
    38.     public int someInt;
    39.     public float someFloat;
    40.     public bool someBool;
    41. }
    42.  
    43.  

    FInally here is an example of how to read an XML file in Unity. I've included a section that actually writes the file too, though in theory you wouldn't do that in Unity but in your own editor program. This script is attached to a GameObject.
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.IO;
    4. using UnityEngine.UI;
    5. using UnityEngine.EventSystems;
    6. using System.Reflection;
    7. using System;
    8.  
    9. public class XMLLoader : MonoBehaviour
    10. {
    11.     XMLData data;
    12.     XMLData newData;
    13.  
    14.     void Awake()
    15.     {
    16.         data = new XMLData();
    17.         newData = new XMLData();
    18.     }
    19.     void Start()
    20.     {
    21.         // Create an XML File based on the what we store in the data object
    22.         WriteXMLFile();
    23.  
    24.         // Read it back out into newData
    25.         newData.Load(Path.Combine(Application.dataPath, "testXml.xml"));
    26.  
    27.         Debug.Log("This shoudl print 3.14149: " + newData.someOtherClass[1].someFloat);
    28.     }
    29.  
    30.     void WriteXMLFile()
    31.     {
    32.         // Ideally you would Write your XML with a separate editor program you write
    33.         // That uses this same XMLData class.   This is just for example purposes.
    34.  
    35.         data.someString = "TestString";
    36.         data.myVector = new Vector3(1.0f, 2.0f, 3.0f);
    37.         data.someOtherClass = new SomeOtherClass[2];
    38.  
    39.         data.someOtherClass[0] = new SomeOtherClass();
    40.         data.someOtherClass[1] = new SomeOtherClass();
    41.  
    42.         data.someOtherClass[0].someInt = 5;
    43.         data.someOtherClass[0].someFloat = 4.5f;
    44.         data.someOtherClass[0].someBool = false;
    45.  
    46.         data.someOtherClass[1].someInt = 10;
    47.         data.someOtherClass[1].someFloat = 3.14159f;
    48.         data.someOtherClass[1].someBool = true;
    49.  
    50.         // this will save it to your projects Asset Directory
    51.         data.Save(Path.Combine(Application.dataPath, "testXml.xml"));
    52.  
    53.     }
    54. }

    You should be able to add these 3 files to a fresh project and see them write an XML file to your assets folder of your project.

    Note this is a good system for creating an entire array of weapons/gear and loading them into your game. Each item/gear should also contain some int that is a Unique ID that no other gear/weaapon has. Then when you store your player's actual gear, you just store an array of these IDs. On game loadup your game loads all the weapons/gear info .. then loads the player's ID array and does whatever it needs to do from there to equip him, etc.
     
    Last edited: Feb 8, 2017
  7. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    @Jtoomer I agree that using binary serialization built into Unity can be an excellent way to store data if you have an existing set of data already built into your game (or an existing set of tools to create more, and a way to load them into Unity -- like using blender to create models and Unity imports them as meshes).

    However, if you need to create a database of items from scratch, creating your own editor to make things easier and using XML/JSON as the intermediate steps to save/load these things into unity seems the easiest.

    Also as you can see the static XMLOP class that loads/saves to XML is small and can uses Generics for any class. Writing the actual data class is also pretty quick, so I think the complexity level is very low.
     
  8. Jtoomer

    Jtoomer

    Joined:
    Jan 30, 2017
    Posts:
    38
    Thanks for the help, I read through a bunch of XML documentation yesterday and should have a tool for writing them for the purposes I need working soon. The code you provided for the reader will be extremely useful.

    This has basically been a solo project for me and I never would have figured any of this out without help from the community.
     
  9. smacbride

    smacbride

    Joined:
    Jan 10, 2015
    Posts:
    50
    If you are storing the information locally on the user's hard drive, binary serialization is harder for a user to "hack".
    XML files are easier for the end user to modify outside of your game, and might make it easy for them to cheat...
     
  10. Jtoomer

    Jtoomer

    Joined:
    Jan 30, 2017
    Posts:
    38
    Cheating of this type is a worry of mine but the game is almost entirely Single-Player with the multiplayer (for now) being completely local. If I do online multiplayer of any type I will look into building an anti-cheat program (perhaps a system that compares the values stored in each player's XML files? I dunno, problem for later)

    While I do agree that the Binary Serialization would be more secure, I have people working on the project whom it would be much easier to say "Here is an XML gen tool, just enter the texture name and statistics and I will put it in the game" than "Here is the documentation on Binary Serialization". Thanks for the concern but for right now, I think that XML will work the best.
     
  11. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Also you can easily implement some sort of encryption/decryption inside your Data class. It can write all the values into the xml file encrypted. and decrypt the values coming out. In the long run, unless you have a server that is storing all this data server side and sending it to the client, a competent hacker can manipulate your game. You can put small roadblocks that are the equivalent of a locked gate. It will keep most people out, but if someone really wants to get inside they will.
     
  12. Timelog

    Timelog

    Joined:
    Nov 22, 2014
    Posts:
    528
    If that is your concern then go with ScriptableObjects. That way you can just let the other people in your project create assets for each weapon, way easier and more secure then either xml or binary serialized files imo. Here's a link explaining how to use it: https://unity3d.com/learn/tutorials...nobehaviour-tyranny-glorious-scriptableobject
     
  13. Jtoomer

    Jtoomer

    Joined:
    Jan 30, 2017
    Posts:
    38
    That seems... almost perfect and could be done internally. If I can get it working without too much hassle I might do that instead of trying to generate and read XML files.