Search Unity

XML writing cant use lists

Discussion in 'Scripting' started by phoda, Sep 22, 2017.

  1. phoda

    phoda

    Joined:
    Nov 11, 2014
    Posts:
    384
    So i have made XML writer.
    It has this class to define how XML file looks like:
    Code (CSharp):
    1. public class GameFeaturesXML
    2. {
    3.     [XmlElement("Name")]
    4.     public string name;
    5.  
    6.     [XmlElement("FeatureType")]
    7.     public List<int> featureType;
    8. }
    (i reduced amount of items for this question)
    and reading it works just fine BUT when i want to write List from my program to this XML element (featureType) or when i try to access featureType list to see its contents or even just check with count if anything is in there i just get NullReferenceException.

    where problem could maybe be is how i create variable maybe?
    i create one instance of that file like this:
    Code (CSharp):
    1. GameFeaturesData GFD = new GameFeaturesData();
    where game features data is this class:
    Code (CSharp):
    1. [XmlRoot("Database")]
    2. public class GameFeaturesData
    3. {
    4.     [XmlArray("GameFeatures")]
    5.     [XmlArrayItem("Feature")]
    6.  
    7.     public List<GameFeaturesXML> gameFeatures = new List<GameFeaturesXML>();  //Creates list of previous Class
    8.  
    9.     public static GameFeaturesData Import(string path)
    10.     {
    11.         XmlSerializer serializer = new XmlSerializer(typeof(GameFeaturesData));
    12.         FileStream stream = new FileStream(path, FileMode.Open);
    13.         GameFeaturesData gameFeaturesData = serializer.Deserialize(stream) as GameFeaturesData;
    14.         stream.Close();
    15.         return gameFeaturesData;
    16.     }
    17.  
    18.     public void Save(string path, GameFeaturesData data)
    19.     {
    20.         XmlSerializer serializer = new XmlSerializer(typeof(GameFeaturesData));
    21.         FileStream stream = new FileStream(path, FileMode.Create);
    22.         serializer.Serialize(stream, data);
    23.         stream.Close();
    24.     }
    25. }
    and used it like this:
    Code (CSharp):
    1. Debug.Log(GFD.gameFeatures[i].requiredFeaturesXML.Count);
    in mean time iam using fixed 4 variables to change but i will need dynamic list in future so i kind of need answer to question
     
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    You don't need the [Xml] blocks. Just make sure your classes are [System.Serializeable] and save and load the class. The Lists will be save and loaded at dynamic sizes.
     
  3. phoda

    phoda

    Joined:
    Nov 11, 2014
    Posts:
    384
    I copy xml file to system. Edit it add new stuff delete some and then pass that data to new class which is saved in xml file. Works fine except for list. I made class of which list is made to be serializable
     
  4. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    XmlSerializer doesn't use the Serializable attribute. If you omit the Xml* attributes it just uses the field name.

    So if you fill up a list with data and serialize it what does the XML look like? Does reading that same file back in work?
     
  5. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    Here's an example of the output XML file for an XMLSerialize example project I often share:

    Class:
    Code (CSharp):
    1.     [System.Serializable]
    2.     public class Player
    3.     {
    4.         public string name = "Test Drive Dummy";
    5.         public int health = 100;
    6.         [SerializeField]public List<Guns.Pistol> pistols; //Lists aren't serialized by default, so we have to mark them for serialization with [SerializeField]
    7.         [SerializeField]public List<Guns.Gattling> gattlingGuns;
    8.         [SerializeField]public List<Animals.Animal> animals;
    9.     }
    XML:
    Code (CSharp):
    1. <?xml version="1.0" encoding="Windows-1252"?>
    2. <Player xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    3.   <name>Test Drive Dummy</name>
    4.   <health>180</health>
    5.   <pistols>
    6.     <Pistol>
    7.       <name>Beretta M9</name>
    8.       <priAmmoType>2</priAmmoType>
    9.       <priAmmoMax>15</priAmmoMax>
    10.       <weight>2.1</weight>
    11.       <fireRate>4.6</fireRate>
    12.       <reloadSpeed>1.6</reloadSpeed>
    13.       <isAutomatic>false</isAutomatic>
    14.       <ironSightType>4</ironSightType>
    15.     </Pistol>
    16.     <Pistol>
    17.       <name>Spooky Gun</name>
    18.       <priAmmoType>2</priAmmoType>
    19.       <priAmmoMax>15</priAmmoMax>
    20.       <weight>2.1</weight>
    21.       <fireRate>45</fireRate>
    22.       <reloadSpeed>1.6</reloadSpeed>
    23.       <isAutomatic>false</isAutomatic>
    24.       <ironSightType>4</ironSightType>
    25.     </Pistol>
    26.   </pistols>
    27.   <gattlingGuns>
    28.     <Gattling>
    29.       <name>Big Facking Gun</name>
    30.       <priAmmoType>4</priAmmoType>
    31.       <priAmmoMax>200</priAmmoMax>
    32.       <weight>25.6</weight>
    33.       <fireRate>42.6</fireRate>
    34.       <reloadSpeed>5.3</reloadSpeed>
    35.       <isAutomatic>true</isAutomatic>
    36.       <barrelSpeedMax>3.4</barrelSpeedMax>
    37.     </Gattling>
    38.   </gattlingGuns>
    39.   <animals>
    40.     <Animal>
    41.       <name>Pig</name>
    42.       <feetCnt>4</feetCnt>
    43.       <colorMain>
    44.         <r>0.5</r>
    45.         <g>0.5</g>
    46.         <b>0.5</b>
    47.         <a>1</a>
    48.       </colorMain>
    49.       <weight>2.4</weight>
    50.     </Animal>
    51.     <Animal>
    52.       <name>Black Widow</name>
    53.       <feetCnt>8</feetCnt>
    54.       <colorMain>
    55.         <r>0</r>
    56.         <g>0</g>
    57.         <b>0</b>
    58.         <a>1</a>
    59.       </colorMain>
    60.       <weight>0.001</weight>
    61.     </Animal>
    62.   </animals>
    63. </Player>
    Those are 3 different lists of classes, two of which are derived classes. Their data is serialized as well, and it all loads back fine.
     
  6. phoda

    phoda

    Joined:
    Nov 11, 2014
    Posts:
    384
    could you please also also show Guns.Pistol class or any other from which list is formed. dont quite understand Guns. part but i think Pistol class is something like:
    Code (CSharp):
    1. public class Pistol
    2. {
    3.    string name;
    4.    ...
    5. }
    do you still need to use [XmlElement] for name field in Pistol class?

    in short could you please post like entire example?
     
  7. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    No, no need for XmlElement unless you want to redefine names.
    I've attached the example project.
     

    Attached Files:

    phoda likes this.
  8. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    My point was that this will work without the Serializable attribute on it.
     
  9. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    I wasn't replying to you... I was helping out OP. But yes, the lists don't need the [SerializeAttribute] property since they're public.
     
  10. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Then why did you quote my post?

    I am replying to you and I'm saying your Player class doesn't need to be decorated either.
     
  11. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    Sorry my mistake, been on some all night crunches this week and got the posts mixed up. Yeah to actually save to XML you don't need the [System.Serializeable] above the class, but if you want Unity to show it in the Inspector you do, which most people would want out of their player class.
     
    phoda likes this.