Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Saving a list of items

Discussion in 'Scripting' started by KillTango, Apr 29, 2012.

  1. KillTango

    KillTango

    Joined:
    Apr 29, 2012
    Posts:
    4
    Hi all,

    I have a list of items stored in a variable called 'Inventory' and each item in that list inherits from a custom class called 'Item' which contains string, int, and enum values as well as a texture2d. What I am trying to do is save all of the items in the Inventory list by converting the data in the Item class to strings so I can store them in a temporary string array, and then convert everything back to its original data when loading. I'm getting an error at the line I marked that says 'Format Exception: Input string was not in the correct format.' I'll put my current code up so you can see where I'm at.


    Code (csharp):
    1. //GameSettings.js
    2. var tempArray : String[];
    3. var temp : String;
    4. var Inventory;
    5. var convertVariables : Item;
    6.  
    7. function SaveCharacterData() {
    8. Inventory = GameObject.Find("GUIElements").GetComponent("Inventory").inventory;
    9. for(i = 0; i < Inventory.Count; i++) {
    10.  
    11. if(i != Inventory.Count - 1){
    12. convertVariables.ConvertVariables();
    13. temp += Inventory[i].ToString() + "*";
    14. }
    15.  
    16. else{
    17. convertVariables.ConvertVariables();
    18. temp += Inventory[i].ToString();
    19. }
    20. }
    21. PlayerPrefs.SetString("InventoryItems",temp);
    22. }    
    23.  
    24.  
    25. function LoadCharacterData() {
    26.  
    27. temp = PlayerPrefs.GetString("InventoryItems");
    28. tempArray = temp.Split("*".ToCharArray());
    29.  
    30. for(i = 0; i < tempArray.Length; i++){
    31. Inventory[i] = System.Int32.Parse(tempArray[i]); <<<ERROR OCCURS HERE
    32. }
    33. }
    34.  
    35.  
    36. //Item.js
    37. function ConvertVariables() {
    38. //Ints to convert
    39. price.ToString();
    40. minDamage.ToString();
    41. maxDamage.ToString();
    42. defense.ToString();
    43. healthAmount.ToString();
    44. essenceAmount.ToString();
    45. itemLevel.ToString();
    46. itemFireDamage.ToString();
    47. itemIceDamage.ToString();
    48. itemLightningDamage.ToString();
    49. itemElementDamage.ToString();
    50. curDura.ToString();
    51. maxDura.ToString();
    52.  
    53. //Enums to convert
    54. rarity.ToString();
    55. jewelSlot.ToString();
    56. consumableType.ToString();
    57. armorType.ToString();
    58. armorSlot.ToString();
    59. weaponSlot.ToString();
    60. weaponSlot2.ToString();
    61. weaponDamageType.ToString();
    62. weaponType.ToString();
    63. itemArchetype.ToString();
    64. itemElementType.ToString();
    65.  
    66. //Convert Icon
    67. icon.ToString();
    68.  
    69. Debug.Log("Variables Converted");
    70. }

    The 'ConvertVariables' function obviously is used to convert the ints and enums to strings. What I'm wondering is it possible or even necessary to convert the texture2d to a string? I'm curious because I'm not sure if that's what is causing the error or not. Anyways that's where I'm at right now, if anyone could give some insight it would be greatly appreciated. If you need any more info or code sample I'll be happy to provide it. Thank you!
     
    Last edited: Apr 29, 2012
  2. Tobias J.

    Tobias J.

    Joined:
    Feb 21, 2012
    Posts:
    423
    Hi KillTango, and welcome!

    I'm fairly sure making a texture2d into a string will not do you any favours. Most likely you'll only get the name of it.

    Whatever your problem, it's hard to help without a copy/paste of the error you're getting. Have you seen this?
     
  3. KillTango

    KillTango

    Joined:
    Apr 29, 2012
    Posts:
    4
    FormatException: Input string was not in the correct format
    int.Parse (string) <IL 0x00011, 0x00059>
    GameSettings.LoadCharacterData () (at Assets/Scripts/Character Classes/GameSettings.js:200)
    (wrapper dynamic-method) GameSettings.GameSettings$LoadCharacterData$ (object,object[]) <IL 0x00006, 0x0004c>
    Boo.Lang.Runtime.RuntimeServices.Invoke (object,string,object[]) <IL 0x0004c, 0x00125>
    UnityScript.Lang.UnityRuntimeServices.Invoke (object,string,object[],System.Type) <IL 0x00018, 0x000a6>

    That's the full error message. I actually used to be a member here and I've been coding for a while but I am abosolutely lost on this one. I'll check out the burgzerg tutorials and see if I can find any help there. In the meantime if anyone else has any suggestions I'm open to trying just about anything at this point. Thank you!
     
    Last edited: Apr 29, 2012
  4. Tobias J.

    Tobias J.

    Joined:
    Feb 21, 2012
    Posts:
    423
    Sorry, I probably skimmed your post too fast (posts = 1 speaks volumes ;-)

    I've tried to see through this, but boo seems really weird to me. When looking at ConvertVariables() I don't even see how it works, and it seems simple enough.

    nuff said. I know nothing and wont pretend to again (at least not here).
     
  5. Bluntweapon

    Bluntweapon

    Joined:
    Feb 24, 2012
    Posts:
    158
    Fairly sure that's UnityScript. BOO characteristically has no semicolon to close lines (it lets formatting do that for you)

    Not by calling the ToString function, that just returns the name of reference to the texture. You could write a custom method to do so, but you'd have to write another to construct it back into a texture2d, and to be honest I don't even know how to do that.

    From what I see it that method does nothing but print out the line "Variables Converted". ToString by itself doesn't do anything but return a string representation of an object, but what that string actually gives you is different depending on each object. Actually, unless an object in Unity implements otherwise (such as Vector3 or a Quaternion), it inherits the method from Object, which only gives you the name of said object. See here.

    Since you ask for the string representation of a all the attributes but never actually do anything with them, that method effectively does nothing.

    What's probably causing the error is the fact that
    Code (csharp):
    1.  
    2. temp += Inventory[i].ToString() + "*";
    3.  
    saves the name of the inventory item to the string, so when you try to read it out again
    Code (csharp):
    1.  
    2. Inventory[i] = System.Int32.Parse(tempArray[i]);
    3.  
    it's trying to parse "Magician's Staff" or something into an int.


    Random fact, when you call
    Code (csharp):
    1.  
    2. Debug.Log( someObject );
    3.  
    internally it actually does
    Code (csharp):
    1.  
    2. Debug.Log( someObject.ToString() );
    3.  
    So use that to your advantage and see what you're saving.
     
    Last edited: Apr 29, 2012
  6. KillTango

    KillTango

    Joined:
    Apr 29, 2012
    Posts:
    4
    Ok, I did as you suggested BluntWeapon and I got some pretty peculiar results.

    Inventory prints: 'Item'
    tempArray prints: 'ItemItemItem'
    temp prints: 'ItemItemItem*Item*ItemItem*Item*ItemItem*Item*ItemItem*ItemItemItemItemItemItemItemItemItemItemItemItemItem'

    Yeah..and that's when I only had one item in my Inventory called Short Sword.
    But as you pointed out the methods I am using will not do what I am trying to achieve anyway so I'm pretty much back to square one.
    I really hope some superstar coder can make sense of this because these results make me feel even more lost.
     
    Last edited: Apr 29, 2012
  7. Bluntweapon

    Bluntweapon

    Joined:
    Feb 24, 2012
    Posts:
    158
    LOL yeah that's pretty much what I expected, though in your case tempArray ended up "ItemItemItem" could be because you may have tried to save several times, and you don't reset the "temp" string at all anywhere, you just add to the end of it. I think you may also be a little behind on programming skills in general, so you might want to look for some resources to help with that.

    Serialization of data is never easy to figure out, and there's no easy way out here. I can only point you in the right direction, as I don't know JS nearly as well as I do C#.

    I assume this custom class your inventory inherits from is a class called Item. What you can do is implement a ToString() method yourself in Item to override inherited behaviour, that way when you call ToString() on an item you actually get a string you expect.

    I'm speculating, but your Item class probably will look something like this
    Code (csharp):
    1.  
    2. enum RARITY{
    3.     COMMON,
    4.     UNCOMMON,
    5.     RARE
    6. }
    7.  
    8. enum JEWELSLOT{
    9.     HEAD,
    10.     HANDS,
    11.     FEET
    12. }
    13.  
    14. var price : int;
    15. var minDamage : int;
    16. var maxDamage : int;
    17.  
    18. var rarity : RARITY;
    19. var jewelSlot : JEWELSLOT;
    20.  
    21. public var someTexture : Texture2D;
    22.  
    23. //This will output a string we want
    24. function ToString(){
    25.     var temp : String = "";
    26.    
    27.     temp += price + "*";
    28.     temp += minDamage + "*";
    29.     temp += maxDamage + "*";
    30.    
    31.     temp += parseInt( rarity ) + "*";
    32.     temp += parseInt( jewelSlot ) + "*";
    33.    
    34.     temp += someTexture.name;
    35.    
    36.     return temp;
    37. }
    38.  
    39. //This should reconstruct the item we want
    40. function constructObject( temp : String ){
    41.     var tempArray = temp.Split("*"[0]);
    42.    
    43.     price = parseInt( tempArray[0] );
    44.     minDamage = parseInt( tempArray[1] );
    45.     maxDamage = parseInt( tempArray[2] );
    46.    
    47.     rarity = parseInt( tempArray[3] );
    48.     jewelSlot = parseInt( tempArray[4] );
    49.    
    50.     //In order for the following to work, the texture must be in the Resources folder
    51.     //Note that it may cause its own problems if you plan to run in a Webplayer, but you're probably not concerned about that right now
    52.     someTexture = Resources.Load( tempArray[5] );
    53. }
    54.  
    Then, the other script can reference this
    Code (csharp):
    1.  
    2. function SaveCharacterData() {
    3.  
    4.     var inventory = //However you grab your inventory
    5.     var saveString = "";
    6.    
    7.     for(var i : int = 0; i < inventory.Count - 1; i++) {
    8.         saveString += inventory[i].ToString();
    9.         saveString += "$";//Add a different symbol to denote we've finished serializing an item
    10.     }
    11.    
    12.     //Add the last item
    13.     saveString += inventory[inventory.Count - 1].ToString();
    14.  
    15.     PlayerPrefs.SetString( "InventoryItems", saveString );
    16. }
    17.  
    And to load it
    Code (csharp):
    1.  
    2. function LoadCharacterData() {
    3.  
    4.     var loadString : String = PlayerPrefs.GetString("InventoryItems");
    5.     var allItems = loadString.Split("$"[0]);//Split into separate items first
    6.    
    7.     for(var i : int = 0; i < allItems.Length; i++){
    8.    
    9.         var itemString = allItems[i];
    10.         var someItem : Item = new Item();
    11.         someItem.constructObject( itemString );
    12.        
    13.         //Do something with the item
    14.     }
    15. }
    16.  
     
    Last edited: Apr 29, 2012
  8. KillTango

    KillTango

    Joined:
    Apr 29, 2012
    Posts:
    4
    Well that's certainly a good start. Thank you for taking the time to write all that out. I just woke up and need to finish working on my first cup of coffee before I attempt this again. Will report back in a bit.