Misc

Table of content

Editor assembly

Mostly, database works inside Editor assembly the same way as it works at runtime, meaning you can develop your own Editor tools on top of the database

Use generated classes to access database. To save database in Editor via C# code, use this call:

    using BansheeGz.BGDatabase.Editor;
    //...
    //save database
    BGRepoSaver.SaveRepo();
    //if BGDatabase window is opened- mark database as saved
    if(BGRepoWindow.Active) BGRepoWindow.Instance.MarkRepoSaved();

To assign unity asset field values, use SetAsset method, defined on each unity asset field and available in Editor assembly (this method is not available at runtime assembly)

    SetAsset(int entityIndex, UnityEngine.Object asset)

Events

Events let use listen to database changes, like changing the field or entity, adding or removing entities. Make sure

  1. To pair adding a listener with removing a listener to prevent memory leaks
  2. all events handlers have try/catch block to prevent exception being fired from event handlers

Following events are available:

Event Description
Field value changed It is fired when provided field value change (any entity)
Entity is updated It is fired when provided entity value change (any field)
Entity is deleted It is fired when provided entity deleted
Any entity is updated It is fired when any entity updated (any field)
Any entity is added It is fired when new entity is added
Any entity is deleted It is fired when any entity deleted
Before any entity deleted It is fired before any entity is deleted
Batch update event Batch update event is fired when BGRepo.I.Events.Batch(Action action); method is used. When this method is used, no individual events will be fired while action is being executed and one single batch event will be fired when action is executed. This is required for performance's sake when massive changes to database should be done without firing individual events
Any change event It is fired on any database change

For usage example, see this demo C# script

Validation

Data validation allows to set the rules to validate data. Validation works in Unity Editor only and has no effect at runtime. To turn on validation, press on "Validation off" button at the top left of BGDatabase window.

Validation types
  1. Database data validation
  2. Scene objects validation (Binders and BGEntityGo components)
Database data validation
Validation rule Description
Entity name is unique If entity has a name, it should be unique
Entity name is empty Entities should have no name (names can be cleared under Configuration tab)
Entity is singleton Only one single entity should exist
Field is required Field should have some value. Only class-based fields are affected, cause struct-based fields always have a value
Key is unique Each key, marked as unique, should have 0-1 matching rows. If there are more than 1 matching row, it's considered to be a rule violation.

To review validation log, hover over red E icons as shown on the screenshot below. E icon is shown only if at least one error exists.

Scene objects validation

Following BGDatabase scene components can also be validated (using Scene Explorer tab).

  1. BGEntityGo components
  2. Generated Monobehaviour classes (extending from BGEntityGo)
  3. Data binders

Any component, which has an error, will be highlighted.

Keys and indexes

  1. Key consist of 1-n fields and can be used to look up row(s) quickly. It also can be used in rows validation
  2. Index has a reference to a single field and can be used for effective range scan

Here is a table, comparing different row(s) retrieval methods efficiency

Method Underlying structure Time complexity Comments
meta.GetEntity(int index) list O(1) fastest method
meta.GetEntity(BGId Id) hashtable O(1)
GetEntity(string name) hashtable O(1) if name field data is not skewed
key.GetEntityByKey(params object[] keys) hashtable O(1) if key's fields values are not skewed
index.FindEntitiesByIndex(indexOperator) b-tree O(log n) if index field data is not skewed
meta.FindEntity(predicate), meta.FindEntities(predicate) N/A O(n), fullscan
Keys

Following fields can be added to a key: bool, int, long, decimal, bool?, int?, long?, string, text, enum, relationSingle.

You can access the matching row(s) directly without searching, using BGKey class. Available options:

  1. Use generated methods (recommended)
  2. Use basic API. To access the key, use BGMetaEntity.GetKey({keyName}) method. To get a row(s), use BGKey.GetEntityByKey or BGKey.GetEntitiesByKey methods
  3. If you use Visual Scripting assets, you can use generated unit/node if it's supported

Keys make row(s) access faster, but uses extra memory and may slow down write (update) operations, so do not use keys for data, which is updated frequently.

Indexes

Indexes enables row(s) range scan fast operations, but uses extra memory and may slow down write (update) operations. Currently only single field index is supported. Available options to use an index:

  1. Use generated methods (recommended)
  2. Use basic API. To access the index use BGMetaEntity.GetIndex({indexName}) method. To query rows use index.FindEntitiesByIndex method

Views

Views are virtual table, which does not have its own rows and used with view relational fields. Read more about views here

Command Line

Command line utility (Settings->Command line) let you run DDL-like commands with simplified syntax.

Syntax is (use empty line to separate commands):

    COMMAND [Options]
    [Additional options]

Available commands:

  1. CREATE TABLE [TableName]
    [FieldName] [FieldType]
  2. ALTER TABLE [TableName]
    ADD [FieldName] [FieldType]
    DROP [FieldName]
  3. DROP TABLE [TableName]

Example:

    CREATE TABLE MyTable
    MyField1 int
    MyField2 bool

    ALTER TABLE MyTable
    ADD MyField3 int
    DROP MyField1

    DROP TABLE MyTable

Custom fields implementation guide

  1. Do not use custom fields unless all other alternatives are much worse. For example, if your custom field has two properties (int and float) there is no need to create a custom field, you can use two basic fields instead (int and float) to store the values.
  2. Do not try to create your custom field in your actual project. Create and test your custom field using a new, empty project. Make sure it works correctly before transferring this field to your project. A bug in your implementation can break the whole database
  3. Use existing fields implementations as examples. Fields implementation sources can be found in Assets\BansheeGz\BGDatabase\Scripts\BGDatabaseSourceCode.unitypackage package (Database\Field\*). Fields managers implementation sources can be found in Assets\BansheeGz\BGDatabase\Editor\Scripts\BGDatabaseEditorSourceCode.unitypackage package (Database\Field\*).
  4. To create a custom field you need to create two C# classes:
    1. Class for the field (in runtime assembly)
    2. Class for the field's manager (in Editor assembly)
  5. [Important] Do not try to create your classes from scratch, extend them from existing classes.
    For your field class:
    1. If your field value is a class extend your field class from BGFieldCachedClassA class
    2. If your field value is a struct extend your field class from BGFieldCachedStructA class
    For your field's manager class:
    1. If your field value can be edited "in place" (like primitive fields: int, float, string)- extend your field's manager class from BGFieldManagerInlinedA class
    2. If your field value can be edited in popup window, which can be opened by clicking on cell button (like complex fields: bounds, assets)- extend your field's manager class from BGFieldManagerWithButtonA class
  6. The methods/properties, which need to be implemented for your field class:
    1. ToBytes/FromBytes- for binary serialization
    2. ToString/FromString- for string serialization
    3. CreateFieldFactory- utility method for creating new fields
    4. Implement ICloneable interface for your value type if it's a class (not struct)
    5. ValueSize property if your value type is a struct
  7. If you have difficulties implementing your own custom field- contact us and send us full source code for your value type (class/struct). You can skip its methods but all fields which needs to be saved inside database need to be included.

Default field value

Default field value is the default value for new rows, i.g. it's the value for rows, created after this default value is set. Default field value is assigned at the moment a row is created and does not affect existing rows values.

Default field value is provided as a string value. Each field type has its own string format, for example for int values it's an int constant (10), for float value it's a float constant (10.1), for bool value it's 0 or 1. If you are not sure which string format to use for your particular field type- create a row with the value, you want to use as a default value and export it to Excel. Than copy Excel cell value and paste it to "Default value" column.