Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

BG Database (inMemory database | Excel/Google Sheets syncing | CodeGen | Save/Load support)

Discussion in 'Assets and Asset Store' started by BansheeGz, May 3, 2018.

  1. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    Hello, you want to include database file to your addressables package?
    BGDatabase supports loading from any location with a custom loader (including addressables), but I'm not sure about localization plug-in.
    Let me check it and if it does not- we will add such a feature.
    I will send you an example with a guide as soon as it's ready

    EDIT: an example project for loading database files from Addressables system with localization addon enabled can be downloaded from here https://www.bansheegz.com/BGDatabase/Downloads/ExampleLocalization/#customLoader
     
    Last edited: Jun 18, 2020
    mike6502 likes this.
  2. VikasYadav

    VikasYadav

    Joined:
    Jul 13, 2019
    Posts:
    1
    Hey ! BansheeGz , Nice Asset .
    But i need your Help.
    To Code Example , I only can access the BgDatabase data., but how can i fill the Database to my excel data.
    Or i need to fill the whole excel data manually in Database and then i have to access .
    Can you Please Let me Know how can i store My excel data to Database .
    Thankyou in Advance !
     
  3. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    Hi!
    I wrote a little tutorial on how to import data from Excel file below (under spoiler tag)
    Additional information is available here:
    1. https://www.bansheegz.com/BGDatabase/ThirdParty/Excel/
    2. https://www.bansheegz.com/BGDatabase/ExportImport/
    Please, let me know if you have any questions!

    1) Backup your excel file just in case.
    2) Select "DataSources" and create "Excel" data source. Set path to your xls file location

    3) Select "Export/Import" and create "Excel" job, set data source to your Excel data source and mark the tables you want to import data for. You can do it by clicking on the "Create custom settings" next to the table name and toggling on "Add missing"/ "Remove Orphaned"/"Update matching" toggles.
    If you already have some data in the table you want to import, uncheck "Remove Orphaned" toggle

    4) Open your xls file. We use a naming convention to map the data for import/export.
    Excel sheet should have the same name as your database table and the first row should have field names (case sensitive). You can skip(ignore) "name" field.
    You need to repeat this step for every table you want to import.

    5) [Optional] If you want to keep the links between Excel rows and database rows, so you could update data either in Excel or database and import/export it multiple times, add "_id" column (without quotes) to your Excel file.
    Ignore this step if you want to import data only once

    6) Save and close your Excel file, save your database, switch to "Export/Import", chose your Excel job and click on the "Import" button
    After importing switch to "Log" tab and search for messages, highlighted in red. If your data has a wrong format, which can not be parsed, you'll get a warning message. Make sure you do not have such messages

    7) Switch to "Database" tab and review imported data. If everything is ok, you can save the database. Otherwise, click on the "Reload" button to revert the changes and try importing again
     
  4. mike6502

    mike6502

    Joined:
    Oct 5, 2016
    Posts:
    5
    I am migrating assets from the Resources folder to Addressables using the BGDatabase Addressables addon. It works fine, but I feel like I might be over-complicating things.

    Previously, via code generation, BGDatabase would handle the Resource.Load action for an asset synchronously.

    Code (CSharp):
    1. var sprite = GameDB.MyItems.GetEntity(itemName).itemSprite;
    Now, with Addressables, I need an extra line to get the Addressable address, and then do the addressables load process asychronously.

    Code (CSharp):
    1. var entity = GameDB.MyItems.GetEntity(itemName);
    2. var address = GameDB.MyItems._itemSprite.GetAddressablesAddress(entity.Index);
    3.  
    4. Addressables.LoadAssetAsync<Sprite>(address).Completed += op => {
    5.   if (op.Status == AsyncOperationStatus.Succeeded) {
    6.     var sprite = op.Result;
    7.   }
    8. };
    That's a lot more code than before. Is there a simpler approach?
     
  5. castor76

    castor76

    Joined:
    Dec 5, 2011
    Posts:
    1,865
    You could simply preload the asset at the beginning of the game loading time. There is an example script included in the package.
     
  6. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    @mike6502
    @castor76

    Yes, preloading assets could be another alternative, but it has one big drawback- it adds additional code/complexity, I still believe that using asynchronous Addressables API without preloading is a more robust way to load assets.

    Here is another option- we have added additional methods for asset fields with Addressables loader (Load{FieldName}Async)
    They still load assets asynchronously, but they hide Addressables boilerplate code and also no need to set asset type.
    Example: Code generator generates the following method for "itemSprite" Sprite field:
    Code (CSharp):
    1.  
    2. public void LoaditemSpriteAsync(Action<UnityEngine.Sprite> completedCallback)
    3. {
    4.    var address = _itemSprite.GetAddressablesAddress(Index);
    5.    if(string.IsNullOrEmpty(address)) return;
    6.    Addressables.LoadAssetAsync<UnityEngine.Sprite>(address).Completed += op => {
    7.        if (op.Status == AsyncOperationStatus.Succeeded) completedCallback(op.Result);
    8.    };
    9. }
    10.  
    and it can be used like this:
    Code (CSharp):
    1.        
    2. MyItems.GetEntity(0).LoaditemSpriteAsync(sprite =>
    3. {
    4.    
    5. });
    6.  
    mike6502, I sent you a beta package in a private message just in case you might be interested.

    Also, if you want to customize this method, you can add your own methods to generated classes.
    Since all generated classes are partial, you can create your own class with the same name and add additional methods to it.
    Let's say you want to throw an exception in case a value is not set.
    You can add the following method:

    Code (CSharp):
    1.  
    2. using System;
    3. using UnityEngine.AddressableAssets;
    4. using UnityEngine.ResourceManagement.AsyncOperations;
    5.  
    6. namespace GameDB
    7. {
    8.     public partial class MyItems
    9.     {
    10.         public void LoadItemSprite(Action<UnityEngine.Sprite> completedCallback)
    11.         {
    12.             var address = _itemSprite.GetAddressablesAddress(Index);
    13.             if (string.IsNullOrEmpty(address))
    14.                 throw new Exception("Value is not set. Entity=" + Name);
    15.  
    16.             Addressables.LoadAssetAsync<UnityEngine.Sprite>(address).Completed +=
    17.                 op =>
    18.                 {
    19.                     if (op.Status == AsyncOperationStatus.Succeeded)
    20.                         completedCallback(op.Result);
    21.                 };
    22.         }
    23.     }
    24. }
    25.  
     
  7. castor76

    castor76

    Joined:
    Dec 5, 2011
    Posts:
    1,865
    While I do agree with above, I found that while I use database, say for example item. Async operation was not an option.
    You really don't want to wait for it to load and it also adds complexity during actually using it. I did not want any middle man hanging around when all I wanted is to get the value or an asset from database.

    Preloading does indeed adds complexity in the beginning of the game loading time, but that's just one place you deal with. And then rest of the game related code is free from all this Async business.

    Choice is there so it's always a good thing!
     
  8. mike6502

    mike6502

    Joined:
    Oct 5, 2016
    Posts:
    5
    Thanks @BansheeGz, the beta package with updated code gen works great for me. My code is now much simpler.

    I also didn't realize that the generated classes were partial - that's great to know.

    @castor76, you're right, preloading will work for some of my assets. The use case I mentioned above is with an in-game catalog where players scroll and choose from hundreds of items. Preloading is not optimal there, and is one of many reasons why I am migrating away from Resources.

    Thanks!
     
    BansheeGz likes this.
  9. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    @castor76
    @mike6502

    The main concern about preloading technique is that it relies on internal addressables cache, which returns an asset synchronously after this asset was loaded for the first time
    I doubt that this behaviour is part of the public addressables interface.
    We do use standard LoadAssetAsync method, but the fact that asset is returned immediately could be some side effect.
    It's really hard to predict how this cache acts in all possible situations.
    So I do believe that using async addressables API is a safer option.
     
  10. castor76

    castor76

    Joined:
    Dec 5, 2011
    Posts:
    1,865
    I am all using preloading in my game so I will be watching out for any problems in the future.
     
    BansheeGz likes this.
  11. m-y

    m-y

    Joined:
    Sep 22, 2013
    Posts:
    455
    Hi @BansheeGz
    i am willing to buy your plugin but i have important question
    what i am looking for is Edit Existed Excel File that already have some values like
    String
    numeric
    and images

    so can i edit the cell in the excel file without losing the existed data
    like images and file Design of table ?
    if yes
    does the plugin support WebGL ?
    Thanks
     
  12. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    Hi!

    1) WebGL is supported.
    2) The asset supports 2-way data transfer (export and import) between database and excel file.
    Additional _id column is required in an excel sheet to link excel row with database row.
    This column is filled automatically.

    But unfortunately, we do not support binary data transfer (like images etc.).
    All assets, stored in our database, are stored by reference.
    These references can be paths to the assets (if Resources folder is used) or address/GUID (if addressables system is used)
    So once data is transferred to excel file, these references are transferred as strings values, not assets themselves.

    Probably it's possible to create a custom extension to transfer images as well.
    The problem with images inside an excel file is that they are not linked to rows/cells, they are just floating on top of the cells, so we have to come up with some custom mapping agreement how to map these images to particular rows/fields, I'm not sure yet if it's possible (at least without complicated setup)

    If you are still interested, please, write to our support email support@bansheegz.com
     
    Last edited: Jul 13, 2020
  13. DG_Adriano

    DG_Adriano

    Joined:
    Aug 10, 2019
    Posts:
    29
    Hi, I´v just tried migrating my project from Resources Folders to Addressables, all looked fine but I´m having trouble instantiating my assets using Bolt 1, the field just returns Null, I´m sure there is a correct way of doing this.

    Any suggestions or considerations?

    Thanks.
     
  14. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    Hi

    You can load assets from addressables system using this custom Bolt unit:
    https://www.bansheegz.com/BGDatabase/Downloads/RuntimeAddressablesBolt/

    I've sent you an example project in a private message, which demonstrates how to use this custom unit in case you might be interested

    Please, let me know if you have any questions
     
    DG_Adriano likes this.
  15. DG_Adriano

    DG_Adriano

    Joined:
    Aug 10, 2019
    Posts:
    29
    Your support is outstanding! I´ll let you know if things gone alright.
     
    BansheeGz likes this.
  16. DG_Adriano

    DG_Adriano

    Joined:
    Aug 10, 2019
    Posts:
    29
    Another one, is it easy to add my custom class as a Field option? How would I do it.

    My class is simple, here´s it:

    using Ludiq;
    using System;
    using UnityEngine;

    using System.Collections;
    using System.Collections.Generic;

    namespace IslandMap {
    [Serializable][Inspectable]
    public class Mapa {
    public int Terrain { get; set; }
    public List<Slot> Slots {get; set;}
    public List<Vertice> Vertices {get; set;}
    }
    }
     
  17. DG_Adriano

    DG_Adriano

    Joined:
    Aug 10, 2019
    Posts:
    29
    Also, is it possible to store a byteArray ( byte[] ) ? if its too hard to add a custom type, storing byte array would solve it too.
     
  18. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    @DG_Adriano
    Implementing either of them (a custom field or a byteArray field) should not be a problem.
    We need Slot.cs and Vertice.cs source files as well to implement a custom field.

    But there are also other alternatives, which may be a better choice in many cases.
    1) Instead of storing byte array inside the database, you could store this array as an asset (a file with "bytes" extension)
    Such files can be loaded by Unity as TextAssets https://docs.unity3d.com/ScriptReference/TextAsset.html
    You can reference these files from a database using "unityObject" field
    Optionally "UnityEngine.TextAsset" (without quotes) constraint can be added while creating unityObject field
    Then just put all these assets to addressables system and load them just like any other asset
    Use "bytes" property of TextAsset asset to access byte array. https://docs.unity3d.com/ScriptReference/TextAsset-bytes.html
    Such an approach should be a better option especially if the sizes of these arrays are big enough

    2) Instead of implementing a custom field, you could try to use multiple regular fields.
    So for "Map.Terrain" field use an "int" field
    For "Map.Slots" / "Map.Vertices" fields you could try to use a nested field https://www.bansheegz.com/BGDatabase/SupportedFields/#nested
    The nested field creates a connected list of entities.
    And these entities can have any set of supported regular fields
    I would not recommend using this approach though if the amount of data is big (option #1 is better choice in this case)

    If you still prefer to create a custom field or byteArray field- please, let me know
     
  19. DG_Adriano

    DG_Adriano

    Joined:
    Aug 10, 2019
    Posts:
    29
    That clarify a lot, thanks, I´ll try the first option.
     
  20. NoConscience

    NoConscience

    Joined:
    Mar 16, 2019
    Posts:
    12
    Hi, I'm trying to bind locale value at some point.
    I'm wondering that below is the only way to bind Manually?
    Code (CSharp):
    1. BgDataBinderFieldGo b;
    2. b.Bind();
    There is no way to bind all field at one time?
    It's better if it include disabled gameobjects.
     
  21. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    Hi,
    The parent class of all binders is BGDataBinderGoA
    It's just a regular MonoBehaviour script, so all functions, applicable to MonoBehaviour are also applicable to all binders
    You can find all the binders (including the disabled ones) and call Bind on each of them
    I think the code below should work fine (the code is based on this answer http://answers.unity.com/answers/1272001/view.html )
    This method can be very expensive (I guess, it depends on a number of GameObjects in your scenes)
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using BansheeGz.BGDatabase;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5.  
    6. private static void BindAll()
    7.     {
    8.         var results = new List<BGDataBinderGoA>();
    9.         for(var i = 0; i< SceneManager.sceneCount; i++)
    10.         {
    11.             var scene = SceneManager.GetSceneAt(i);
    12.             if (!scene.isLoaded) continue;
    13.             foreach (var go in scene.GetRootGameObjects()) results.AddRange(go.GetComponentsInChildren<BGDataBinderGoA>(true));
    14.         }
    15.         results.ForEach(binder => binder.Bind());
    16.     }
    17.  
     
  22. DG_Adriano

    DG_Adriano

    Joined:
    Aug 10, 2019
    Posts:
    29
    Hi, ended up I´m using a json String to save my data, I believe it will do.

    And would like to report something that's not really an issue but is affects the workflow with bolt, the save unit make stuff after it dimmed:
     

    Attached Files:

    • temp.PNG
      temp.PNG
      File size:
      230.3 KB
      Views:
      21
    BansheeGz likes this.
  23. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    Yes, it should work fine.
    If you are still interested in custom/binary array field- please, let me know - we could add it

    Thank you for reporting this issue!
    We have fixed it (I've sent a package with a fix in a private message)
     
  24. DG_Adriano

    DG_Adriano

    Joined:
    Aug 10, 2019
    Posts:
    29
    Wonderful, thanks!
    Now that Bolt is official and free, you have a nice head-start supporting it! congratulations.
     
  25. ronripsyche

    ronripsyche

    Joined:
    May 29, 2018
    Posts:
    4
    I'm having some trouble finishing the GoogleSheet procedure.. I think everything is set but I'm missing something crucial since the googlesheet won't update.

    I was creating a document for a quick and simple setup for my team, I'll link it here since I'm unsure if I messed on step 9 or 13: https://drive.google.com/file/d/1Td_hxmrM6wTMYdqOQYBhEoSdXNKcisYw/view

    This is meant for research projects, so all I really need is to send static inputs (ints, bools, strings) from other scripts (Results.cs in this example) to a googlesheet at the end of an experiment.

    The next step would be inserting a new line below each time "SaveResults()" is called, as to not overwritte previous users data.
     
  26. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    Hello,

    If all you need is to append new data to the existing GoogleSheets spreadsheet, I think the best method (by far) is to use a Google Form connected to GoogleSheet spreadsheet
    I wrote a little tutorial on how to do it in case you might be interested (below, under spoiler tag)
    This method is robust and has minimal setup.
    All that is required to append a new row- is to invoke HTTP POST with specified parameters
    These parameters are: Form Id and field names
    You do not need to use BGDatabase for this method
    Please, read the guide below for more details
    There are also methods for posting data directly to GoogleSheets (without using GoogleForms), like this one https://dev.to/omerlahav/submit-a-form-to-a-google-spreadsheet-1bia but we did not test it and I do not think it's much better than the described method

    We do not recommend to use BGDatabase in this scenario
    LiveUpdate addon can only import the data, it can not export it
    SaveLoad addon is for saving database runtime changes locally (to a file), it's not related to google sheets.
    We provide a plugin to export/import data to GoogleSheets at runtime https://www.bansheegz.com/BGDatabase/Downloads/RuntimeGoogleSheets/ , but the export procedure has one big limitation- it can not be executed simultaneously by multiple clients. We are researching methods to bypass this limitation, but I can not tell when (if) the solution will be available

    1) Create a Google form https://support.google.com/docs/answer/6281888 and add all the fields
    Your GoogleForm will look like this:


    2) Link your form to your GoogleSheet speadsheet https://support.google.com/docs/answer/2917686?hl=en (Choose where to store responses)


    3) Now the tricky part- you need to find out HTML form field names
    3.1) Click on the form's "Preview" button

    3.2) Open developers tool for your browser (F12 key for Chrome or Firefox)
    and run the following script in the Console
    Code (JavaScript):
    1. function loop(e){
    2. if(e.children)
    3.     for(let i=0;i<e.children.length;i++){
    4.         let c = e.children[i], n = c.getAttribute('name');
    5.         if(n) console.log(`${c.getAttribute('aria-label')}: ${n}`);
    6.         loop(e.children[i]);
    7.      }
    8. }; loop(document.body);
    Search for lines, containing "entry." values- its your HTML field names


    4) FormID can be found in your form URL


    5) FormID and field names are all required information to post new data to google sheets
    Now you can add new rows by calling this code (I attached full C# script to this message - GoogleManager.cs)




    Please, let me know if you have any questions
     

    Attached Files:

    Last edited: Jul 28, 2020
    ronripsyche likes this.
  27. ronripsyche

    ronripsyche

    Joined:
    May 29, 2018
    Posts:
    4
    Thank you very much for the detailed guide and tidy code! It's exactly what I needed. Access to googleform graphs is like a cherry on top.

    I converted most values to strings since I'm unsure there is an alternative, but it still holds the ground well while sending 11 fields simultaneously.

    Eventually I'll find other uses for BGDatabase, can't let this pearl go to waste.
     
    BansheeGz likes this.
  28. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    Thank you so much for your support!
     
  29. Oshigawa

    Oshigawa

    Joined:
    Jan 26, 2016
    Posts:
    318
    Hello @BansheeGz

    Is there a way to move rows from one table to another? I can't find it if there is. Copying/Pasting with M button does not work, it says please copy row first.
     
    Last edited: Aug 3, 2020
  30. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    Hello,
    We've added a tool for moving/copying rows between different tables.
    I've sent you a private message.
     
    Oshigawa likes this.
  31. Oshigawa

    Oshigawa

    Joined:
    Jan 26, 2016
    Posts:
    318
    Thanks, i'll check the PM :)
     
    BansheeGz likes this.
  32. castor76

    castor76

    Joined:
    Dec 5, 2011
    Posts:
    1,865
    Guys whoever comes here to find out about this database asset, this is by far the best one I have ever used in Unity. Support is 5Star quality, the best I have ever experienced in the Asset Store. I own like 400 assets and support from this asset is the best one I got. This asset deserves so much more attention. I can't think of making another Unity game without this.. This is kind of asset that make you want to use Unity despite their own short failing.
     
    BansheeGz likes this.
  33. Oshigawa

    Oshigawa

    Joined:
    Jan 26, 2016
    Posts:
    318
    I'd give 50 stars if i could, one of the best assets and best support ever.
     
    BansheeGz likes this.
  34. castor76

    castor76

    Joined:
    Dec 5, 2011
    Posts:
    1,865
    This asset should be nominated for the award in asset store. Database asset is something that can last as long as, because it isnt really affected by all this URP, ECS business that is been going on forever now.
     
    BansheeGz likes this.
  35. pravinyadav

    pravinyadav

    Joined:
    Jan 24, 2010
    Posts:
    19
    I am using Excel file that is saved as C:\MyExcelFolder\MyExcel.xlsx.
    I have imported BansheeGzExcelRuntime.unitypackage and assigned BGExcelImportGo.cs file and assigned above mentioned excel path.
    I have followed all the instructions given in ExportImport page.
    I can see all the updated changes in editor but it is not reflected in build.
    I mean if I change some information in one cel then I can't see the updated change in build.
    Every time I have to go to BGDatabase Export/import tab click on import then that information is loaded.
    I don't know why I can't see the updated changes in build.
    Please help me solving this issue.
     
  36. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    Hello,
    I wrote a little troubleshooting guide (under the spoiler tag below)
    We also uploaded a new example project to our Excel runtime plugin page- https://www.bansheegz.com/BGDatabase/Downloads/RuntimeExcelMonitor/ ("Example project" section)- maybe it could help as well.

    If you have any questions- please, let me know.

    1) Update ExcelRuntime plugin to the latest version here https://www.bansheegz.com/BGDatabase/Downloads/RuntimeExcelMonitor/

    2) Check BGExcelImportGo component's "Excel File" parameter- make sure it's set to correct file (e.g. C:\MyExcelFolder\MyExcel.xlsx)


    3) Run your scene and access BGExcelImportGo GUI by clicking on "Excel>>" button

    If you do not see this button, set "UI Coordinates" and "Disable GUI" parameters to (10,10) and off (as shown on the first screenshot)

    4) Once you click on "Excel>>" button, you will see BGExcelImportGo GUI, which can be used to run import or export tasks at runtime.
    Click on "Import now" button to run the import task.
    If 1) the file path is set correctly and 2) This file is working fine while running import task from Unity Editor (using "Export/import" tab of BGDatabase window)- I suppose it should work fine as well.
    Pay attention to "Error during run" parameter- the value should be "N/A".
    Here is the example of how GUI should look like if execution completed without any error (I use a single table with a single row and a single field to keep it simple):


    and here is how GUI looks like if some error occurred (wrong file path in this case)


    5) [Optional] Once you make it work properly, you can enable Excel file monitoring, so you do not have to press on "Import now" button every time you change Excel file.
    If "Monitor File" parameter is set to true, a background thread monitors file's modification time and auto-import the data every time the file on disk is modified.
    Change your Excel data and press Ctrl+s to save the file and trigger the import process.


    6) When you make it work properly in Unity Editor- you can test it in build.
    Build your app and use the same steps to test it - e.g. click on "Excel>>" button, then click on "Import now" button and pay attention to "Error during run" parameter- the value should be "N/A".
    There could be some errors, which do not come up in Unity Editor.
    The one, which we know of- "Encoding XXX data could not be found" error- it occurs because Unity does not include internationalization DLLs to the build, the solution can be found on our plugin page https://www.bansheegz.com/BGDatabase/Downloads/RuntimeExcelMonitor/ (Troubleshooting section at the bottom of the page)
     
  37. castor76

    castor76

    Joined:
    Dec 5, 2011
    Posts:
    1,865
    Today, I was wondering if I can add animation curve to the database, and thought "oh man.. this is just way too long shot, there is no way that this could be done...." and wanted to ask developer about it. Then, I thought "oh well, there is nothing to loss to see if it is already there..." and checked it out then .. WOW.. man.... it's really already available.....

    Don't know what else to say... but AWESOME! This is like first time I wanted something implemented from asset from Asset Store and thought had very little chance, and then it's already there.. I will give 50 stars if I could! So thank you!
     
    BansheeGz likes this.
  38. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    @castor76
    Thank you so much for supporting us and helping us to improve the asset!
     
  39. danicrem

    danicrem

    Joined:
    Nov 9, 2014
    Posts:
    45
    Just to share with others the answer I got form support:

    Question:
    Hello, Currently I use the database using the BGDatabase without classes (without generated script). I created a listInt field in one of my tables. Now I want to add integers to this field, remove integers, remove all integers and check if an integer is present in the intList. But I can't find any documentation on the topic. Could you send me a code example?

    Answer:
    You can use List<int> as field's type and use standard C# List methods afterwards to manage list values (see example below)
    Please, let me know if you have any question

    //table name
    string tableName = "test";
    //field name
    string fieldName = "listInt";

    //get table
    BGMetaEntity meta = BGRepo.I[tableName];

    //get first entity
    BGEntity entity = meta.GetEntity(0);

    //get listInt field value
    List<int> listValue = entity.Get<List<int>>(fieldName);

    //if the value is null
    if (listValue == null)
    {
    listValue = new List<int>();
    entity.Set(fieldName, listValue);
    }

    //============ all methods beneath are standard List<int> methods
    //add value

    listValue.Add(1);

    //check if value is present
    var isOneContained = listValue.Contains(1);

    //remove the first occurence of 1
    listValue.Remove(1);

    //remove all objects, which are equal to 1
    listValue.RemoveAll(i => i == 1);

    //remove all objects unconditionally
    listValue.Clear();


    I tried the script and had some problems with the entity.Set(fieldName, listValue);
    What I dis was just to set the listValue and not the fieldName (I had an existing field). The it worked. Else I got two numbers in the field.
     
  40. danicrem

    danicrem

    Joined:
    Nov 9, 2014
    Posts:
    45
    And here is better explaination for the save load system. Now I got it to work. Thank you BanscheeGz!!

    Regarding saving and loading:
    Saving and loading are actually both are 2 steps processes

    To save the changes you need to
    1) Call BGAddonSaveLoad.Save function to obtain byte array
    2) Save this array to a file

    To load the changes you need to
    1) Read the file from disk
    2) Call BGAddonSaveLoad.Load function to load saved changes to database

    Below is detailed guide with C# code


    Saving:
    Step 1/2: To obtain runtime changes you need to run this code
    //// save the game
    byte[] bytes = BGRepo.I.Addons.Get<BGAddonSaveLoad>().Save();
    byte[] bytes is the array of bytes, which has information about the changes- it needs to be saved to some persistent storage- so it can be loaded after game is closed and opened again
    The easiest persistent storage to use- is a file in Application.persistentDataPath folder, so the step 2 is
    Step 2/2: writing these bytes to a file (bg_save_wordy.dat- is a file name)
    // save the game
    File.WriteAllBytes(Path.Combine(Application.persistentDataPath, "bg_save_wordy.dat"), bytes);


    Loading:
    Once you saved the bytes array to a file on disk- you can load it any moment you want
    Step 1/2: first you need to read file content (bg_save_yourname.dat- is a file name)
    // read file content
    byte[] bytes = File.ReadAllBytes(Path.Combine(Application.persistentDataPath, "bg_save_yourname.dat"))

    Step 2/2: After you read file content you can load it to database using following code
    //// load the game Step 2/2
    BGRepo.I.Addons.Get<BGAddonSaveLoad>().Load(bytes);
    Once you loaded file from disk and called BGAddonSaveLoad.Load() function- database state should be changed to the same state the moment it was saved (if you setup SaveLoad settings correclty)


    Regarding LoadSave script you posted
    It can be implemented easier: instead of deriving from MonoBehaviour class, it can be implemented as static class like so
    using System.IO;
    using BansheeGz.BGDatabase;
    using UnityEngine;

    public static class SaveLoadManager
    {
    public static bool HasSavedFile

    {
    get { return File.Exists(SaveFilePath); }
    }


    public static string SaveFilePath

    {
    get { return Path.Combine(Application.persistentDataPath, "bg_save_yourname.dat"); }
    }


    public static void Save()

    {
    File.WriteAllBytes(SaveFilePath, BGRepo.I.Addons.Get<BGAddonSaveLoad>().Save());
    }


    public static void Load()

    {
    if (!HasSavedFile) return;

    BGRepo.I.Addons.Get<BGAddonSaveLoad>().Load(File.ReadAllBytes(SaveFilePath));
    }
    }
    So you do not need to attach it to GameObject- just call
    SaveLoadManager.Save();
    to save and
    SaveLoadManager.Load();
    to load any moment you want


    Example project
    I've created a minimalistic example project- I hope it will help to understand how saving and loading work

    Apart from SaveLoadManager script, I posted above, it has SaveLoadTest.cs script, which tests SaveLoadManager script
    using System.IO;
    using BansheeGz.BGDatabase;
    using UnityEngine;

    public class SaveLoadTest : MonoBehaviour
    {
    void Start()
    {
    if (!SaveLoadManager.HasSavedFile)
    {
    // STEP 1 - no save file exists- change data and save it
    var entity = BGRepo.I["test"].GetEntity(0);
    entity.Set("name", "Name UPDATED");
    entity.Set("persistentString", "Value UPDATED");
    SaveLoadManager.Save();
    print("Saved to " + SaveLoadManager.SaveFilePath);
    }
    else
    {
    // STEP 2 - save file exists- so load it and delete to run Step 1 again next time
    SaveLoadManager.Load();
    print("Loaded from " + SaveLoadManager.SaveFilePath);
    //comment this line if you do not want save file to be deleted
    File.Delete(SaveLoadManager.SaveFilePath);
    }
    }
    }
     
  41. I_Dont_See_Sharp

    I_Dont_See_Sharp

    Joined:
    Jan 30, 2018
    Posts:
    4
    Great package so far!

    Is it possible to bind data using a relationSingle's values?
     
  42. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    Hello!
    We will add this feature to the next release, thank you for the suggestion!
    I will send you a beta package as soon as it's ready in a private message just in case you might be interested
     
  43. danicrem

    danicrem

    Joined:
    Nov 9, 2014
    Posts:
    45
    Here is a bit more information for importing your Excel sheet into BG Database.

    Step 1. Install BG Database and create a new database (use the Configuration tab and create a new row with the + sign next to Meta). The name of the row needs to correspond to the name of the tab in your Excel sheet). If you have multiple sheets, you need to create multiple rows under Configuration Metas with names corresponding to the names of the sheets.
    If you have already a database with some content, you don't need to re-create it.
    Step 2. Create the columns in that database (they also need to correspond to the colums in your Excel sheet). If you have multiple sheets, you need to create the columns for all the rows.
    Step 3. Adjust your Excel file so it gets this structure at the top of the columns
    _id, name, name_first_column, name second_column (and so on)
    Beneith _id you can leave it blank. Beneith "name" you need to create an unique name for each row (I just created a list of 1, 2, 3, 4, 5, and so on. This was because in my first column I had the same names occuring several times. But if your cells all contain a unique name, you can just put "name" above and you will be fine). Next column will be called whatever you like and the next columns too. Just keep the names equal to the names in BG Database.
    Step 4. Open the tab DataSource in BG Database. Click on the + sign to create a new path. It sais it will overwrite an existing file, but it does not. So before you create the path, you can create a copy of your Excel file and place it in the Resource folder or StreamingAssets folder (both need to be created manually by you in the Assets folder). Now you can just point the path to your file. Hit OK (it will not overwrite it, even if it sais so).
    Step 5. Go to the Import/Export tab. Here you hit the + sign next to Jobs. Here you select Excel and type in a name. Next under DataSource you select your data source you created in step 4.
    If you don't see any green in this tab, it is because you skipped step 1 (it needs an existing database with columns to be able to merge new data).
    If you created an Excel wil with blank cells beneith _id, you need to check the Update Ids on Import. This will generate unique ID's in the database (fill up the blank cells under _id).
    Under Merge settings select Merge and ckeck Add missing entities, Remove orphaned enities and Update matching entities.
    Next click on the Import button, above the Log subtab (right top of the BG Database window and beneith Settings).
     
  44. I_Dont_See_Sharp

    I_Dont_See_Sharp

    Joined:
    Jan 30, 2018
    Posts:
    4
    thanks for the steps denicrem!
    The way you can use excel with your project to import, export, initiated, swap settings, is so powerful and very well done.

    This is a gorgeous asset. What it does and provides unlocks a lot of powerful potential.


    Thank you! That is amazing. This will unlock a huge feature-set of possibilities for me.
     
  45. gr3gu

    gr3gu

    Joined:
    Nov 26, 2019
    Posts:
    2
    Hi there!

    First of all, thank you for database plugin, it fits my city-builder project very well and makes my life easier :)

    I started to notice some issues after upgrading Unity to the new version. The most worrying one is the error shown every time I enter the Play Mode:

    Unloading broken assembly Assets/BansheeGz/BGDatabase/Editor/Pluginz/BGDatabaseEditorGoogleSheets.dll, this assembly can cause crashes in the runtime


    I'm not using the google docs / excel feature at all, the only active plugin is the Addressables one.

    There's also a warning:

    Assets\BGDatabaseAddressables\ScriptsNoDll\BGAddressablesPreloader.cs(163,35): warning CS0612: 'Addressables.LoadAssetsAsync<TObject>(IList<object>, Action<TObject>, Addressables.MergeMode)' is obsolete


    But it's obviously connected to the new addressables version.

    There is also a bunch of randomly appearing warnings during the regular database operations as changing tabs or editing rows:

    SendMessage cannot be called during Awake, CheckConsistency, or OnValidate
    UnityEditor.AssetDatabase:LoadAssetAtPath(String)
    BansheeGz.BGDatabase.Editor.<>c__DisplayClass2_0`1:<TryToLoad>b__0(AddressableAssetEntry)
    BansheeGz.BGDatabase.Editor.BGAssetLoaderManagerAddressablesDelegate:Find(String, Func`2)
    BansheeGz.BGDatabase.Editor.BGAssetLoaderManagerAddressablesDelegate:TryToLoad(String)
    BansheeGz.BGDatabase.Editor.BGAssetLoaderManagerAddressables:TryToLoad(String, BGAssetLoaderA)
    BansheeGz.BGDatabase.Editor.BGFieldManagerUnityAssetA`1:Load(BGAssetLoaderManagerA, BGAssetLoaderA, String)
    BansheeGz.BGDatabase.Editor.BGFieldManagerUnityAssetA`1:Edit(BGEntityViewContext, BGField, BGEntity, BGFieldViewContext)
    BansheeGz.BGDatabase.Editor.FieldColumn:OnGui(BGEntity, BGFieldViewContext)
    BansheeGz.BGDatabase.Editor.<>c__DisplayClass64_3:<ShowTheData>b__4()
    BansheeGz.BGDatabase.Editor.BGEditorUtility:Horizontal(Action, GUILayoutOption[])
    BansheeGz.BGDatabase.Editor.<>c__DisplayClass64_0:<ShowTheData>b__0()
    BansheeGz.BGDatabase.Editor.BGScrollView:Gui(Action, Boolean, Boolean, GUILayoutOption[])
    BansheeGz.BGDatabase.Editor.BGTableEntities`1:ShowTheData(List`1, Single, Single)
    BansheeGz.BGDatabase.Editor.BGTableEntities`1:MyGui()
    BansheeGz.BGDatabase.Editor.BGTableEntities`1:Gui()
    BansheeGz.BGDatabase.Editor.BGViewWithDelegate:Gui()
    BansheeGz.BGDatabase.Editor.<>c__DisplayClass11_0:<Gui>b__4()
    BansheeGz.BGDatabase.Editor.BGEditorUtility:Vertical(GUIStyle, Action, GUILayoutOption[])
    BansheeGz.BGDatabase.Editor.<>c__DisplayClass11_0:<Gui>b__0()
    BansheeGz.BGDatabase.Editor.BGEditorUtility:Horizontal(Action, GUILayoutOption[])
    BansheeGz.BGDatabase.Editor.BGSplitPane`2:Gui()
    BansheeGz.BGDatabase.Editor.BGTabbedView:View()
    BansheeGz.BGDatabase.Editor.<>c__DisplayClass36_0:<Gui>b__0()
    BansheeGz.BGDatabase.Editor.BGEditorUtility:Vertical(GUIStyle, Action)
    BansheeGz.BGDatabase.Editor.BGEditorUtility:UniformStyle(Action)
    BansheeGz.BGDatabase.Editor.BGRepoWindow:Gui(Boolean)
    BansheeGz.BGDatabase.Editor.BGRepoWindow:OnGUI()
    UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)


    Can you tell me if BGDatabase is compatible with experimental play mode options? There's this checkbox that improves the Play Mode enter time by disabling the scene and domain reload (Project Settings > Project > Editor > Enter Play Mode Settings). Disabling the reloads improved my workflow a lot, but I believe the database is not compatible with it, as every second time Play Mode was entered, no entities could be found while doing searches. It could be connected to use of singletons (if the CodeGen is fired before entering the Play Mode, the entites are loaded correctly).

    My versions:
    Unity - 2020.1.6f1
    BG Database - 1.6.0
    Addressables Plugin - 1.0
    Addressables 1.16.1
     
  46. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    @grzegorz_unity391
    Hi, thank you for reporting the issues!

    Please, delete these 2 folders:
    1) Assets\BansheeGz\BGDatabase\Editor\Libs
    2) Assets\BansheeGz\BGDatabase\Editor\Pluginz
    We moved all Excel/GoogleSheets integration code into the plugins, so these folders can be safely deleted


    We updated Addressables plugin to get rid of deprecation warning, please, download it here: https://www.bansheegz.com/BGDatabase/Downloads/BGDatabaseAddressables.unitypackage

    Do you store nested prefabs in the database?
    I think it could be a Unity bug with nested prefabs, which was fixed in 2020.2.0b3 version https://issuetracker.unity3d.com/is...rown-when-loading-ui-asset-for-the-first-time

    I've sent you a beta package in a private message, could you, please, try it and let me know if it works as expected or not?
     
  47. gr3gu

    gr3gu

    Joined:
    Nov 26, 2019
    Posts:
    2
    I see that the info about customer support quality wasn't exaggerated at all :D

    Removing the folders did the trick.
    Deprecation message got away after update.

    Yes, I use a lot of nested prefabs. Thanks for the issue link, gonna wait for the 2020.2 to get out of Beta then.

    I've installed the best package you sent me and yes, everything works as expected!

    Many thanks for your help :)
    Keep up the good work!
     
    BansheeGz likes this.
  48. I_Dont_See_Sharp

    I_Dont_See_Sharp

    Joined:
    Jan 30, 2018
    Posts:
    4
    @gr3gu agreed! It has got to be the best support I have ever encountered.
     
    BansheeGz likes this.
  49. Oshigawa

    Oshigawa

    Joined:
    Jan 26, 2016
    Posts:
    318
    Hello @BansheeGz

    I'm having some strange overhead which points to getting the game objects from the table with actions for playmaker created by bgdatabase, please advise. Should i avoid using the addressables in this state perhaps?

     
    Last edited: Oct 9, 2020
  50. BansheeGz

    BansheeGz

    Joined:
    Dec 17, 2016
    Posts:
    172
    Hello,

    1) The call to Addressables system is made only if you try to read the value from the database, e.g. if you try to store the result in some variable. It should not be called if you leave addressable field parameter as "None" (please, see the screenshot)

    2) To read assets from Addressables, please, use this action https://www.bansheegz.com/BGDatabase/Downloads/RuntimeAddressablesPlaymaker/

    3) Reading assets from addressables using generated actions will not work properly unless you use a preloader script, shipped with Addressables plugin- Assets\BansheeGz\BGDatabaseAddressables\ScriptsNoDll\BGAddressablesPreloader.cs (which we do not recommend to use)
     
    Oshigawa likes this.
unityunity