Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Load a list the same way it was saved?

Discussion in 'Scripting' started by KyleStank, Oct 12, 2016.

  1. KyleStank

    KyleStank

    Joined:
    Feb 9, 2014
    Posts:
    204
    So I am creating an Asset for developers. Right now, I'm using AssetDatabase.LoadAllAssetsAtPath() to load assets into a list, and it works, except it gets loaded alphabetically, which is a problem. This is because when the developer adds an Item, say its called "Sword", then that item is assigned an ID of 0. And then, if they add another item called "Axe", that is assigned an ID of 1. Well, when the database is reloaded, "Sword" now has an ID of 0, and "Axe" now has an ID of 1. And these are obviously not the same ID's, and that is a big problem. This is because when they are stored in a folder, they are sorted alphabetically, and that is fine by itself. But since they are sorted, they are also loaded alphabetically, and we don't want that.

    Here is what I need:
    Developer creates two items, "Sword" and "Axe". Sword has an ID of 0, and Axe has an ID of 1. When the database is loaded back up, the Sword has an ID of 0 still, and Axe has an ID of 1 still. Not the other way around.

    Here is code that loads the objects into a list:
    Code (CSharp):
    1. static void UpdateItemDatabase() {
    2.     Object[] assets =
    3.     AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(itemDatabase));
    4.  
    5.     for(int i = 0; i < assets.Length; i++) {
    6.         if(assets[i].GetType() == typeof(Item))
    7.             itemDatabase.Add((Item)assets[i]);
    8.     }
    9. }
    Here is the code that starts when a window is opened/when the database is loaded:
    Code (CSharp):
    1. public static void CreateEditorWindow(ItemDatabase database) {
    2.     window = (ItemDatabaseWindow)GetWindow(typeof(ItemDatabaseWindow));
    3.     window.titleContent.text = "Item Database Editor";
    4.     window.position = windowRect;
    5.     window.Show();
    6.  
    7.     itemDatabase = database;
    8.     itemDatabase.Items.Clear();
    9.     UpdateItemDatabase();
    10. }
    So instead of loading all the Assets into a list, like I am now, how do I keep the same list? I also need to be able to detect any changes made to a file.

    And by the way, I am using ScriptableObjects for the ItemDatabase, and for the Items. So it is a list of ScriptableObjects inside a ScriptableObject. The ItemDatabase is saved as DatabaseName.asset, and the Items are sub-assets of DatabaseName.asset (and they are added with AssetDatabase.AddObjectToAsset()).This isn't where the problem lies, I just thought I would let you know.

    If I need to explain anything, please let me know. I am honestly very frustrated with this, and any help would be freaking amazing.
     
  2. absolute_disgrace

    absolute_disgrace

    Joined:
    Aug 28, 2016
    Posts:
    253
    Are 'Sword' and 'Axe' objects that are held in a set database, or are they generated objects at runtime that you don't know the details of ahead of time?

    My thought is that your serialized class could simply contain an array of Ints. So you just store the object ID in the array, thus preserving its order. When you reload, you simply use the array to regenerate your list again because you have the ID and know what objects to load out of the database.
     
  3. KyleStank

    KyleStank

    Joined:
    Feb 9, 2014
    Posts:
    204
    Yes, the details are known.​
    Now, the ID of an item is returned by calling .IndexOf on the list the item is held in. But the ID of an item is not actually set. What I mean is this:
    Code (csharp):
    1. public int ID {
    2.     get {
    3.         if(itemList == null)
    4.             return -1;
    5.    
    6.         return itemList.IndexOf(this);
    7.     }
    8. }
    So, the ID is never set. This means that if I stored all the ID's, they would all be 0. I should probably start setting the ID of items, but when?

    Also, when the item database is loaded, itemDatabase.Items.Clear() gets called, so there are no items to go on to find what ID matched what.

    So I know I need to make changes to this system, but what should I do? Any tips, because my brain honestly is fried right now. I have been trying everything the last week and I just feel like nothing is working.

    PS:
    This database is not an Inventory database, but rather the database that holds every item in the game(or every item that can be picked up, whatever you want to call it lol). And then, the InventoryDatabase class will add items to an Inventory if they exist on this ItemDatabase.
     
  4. absolute_disgrace

    absolute_disgrace

    Joined:
    Aug 28, 2016
    Posts:
    253
    In standard databasing terms you assign a primary key to each record in your database. So when you build your database of items, assign each item a unique ID that the player never sees. This ID can be as simple as a sequential number, or a string that reads nicely 'SwordofFire+1', or can be a complex string 'Item_001'

    This is the value that you assign to the array when you save, and its what you read back out. This lets you look up your proper table and get all of the values.


    Alternatively, if each of your items are a prefab, you can make use of the resources folder and you just need to save to file the location and name of the prefab. Then you load the prefab to rebuild that list.
     
    KyleStank likes this.
  5. KyleStank

    KyleStank

    Joined:
    Feb 9, 2014
    Posts:
    204
    Okay thanks. I am not going to use the Resources folder because I am trying to build a flexible system that doesn't rely on a specific folder. But I guess I will just use the ID as the item's current index, like I am now, except I will actually set it. Then, I will save an array of Ints like you said, maybe, "int[] loadOrder", then for every int, add the item back that matches that ID.

    I hope this works, and I will try it either later tonight, or tommorow. But thanks, you have helped me quite a lot lol.
     
    absolute_disgrace likes this.
  6. KyleStank

    KyleStank

    Joined:
    Feb 9, 2014
    Posts:
    204
    Sorry for long reply lol. But it worked! Thank you soo much man. I felt so much relief when I solved this problem. :)
     
    absolute_disgrace likes this.