Example breakdown

Description

We created 2 example scenes, which demonstrate all main features of BGDatabase. If you want to learn more about BGDatabase and you have some minimal programming skills- this is probably the best place to start.

Example scenes are simple game prototype, in which you need to gather all objects on 2 levels. Every object has it's own type and some amount of gold attached. As soon as all objects are gathered, new ones will be spawned. The progress can be saved and loaded.

2D version

We also create 2D variant of our 3D game prototype. You can download it here (BG Database is required to run this example). We also created a tutorial video, you can watch it here. If you already created your own database, please revert database to default (example) database as described here (at the bottom of the page)) before installing this package.

Database schema

Here is the database schema, we use for that example.

  1. Scene- is linked to Unity scene, it's name should be equal to Unity scene name. It has following fields:
    1. spawnPosition [Vector3]- position, the player will be moved then he's spawned in this scene
    2. spawnRotation [Vector3]- rotation, the player will be rotated then he's spawned in this scene
    3. bounds [Bounds]- area for spawning objects
  2. Collectable - is Scene's nested field, meaning it defines it's own table (meta), which is connected to Scene table (meta). It stores all collectable objects in the scene and have following fields:
    1. position [Vector3]- position of the object
    2. gold [int]- amount of gold, attached to the object
    3. type [relationSingle]- type of the object
  3. CollectableType - type of the Collectable
    1. prefab [unityPrefab]- prefab to use as an object to spawn
    2. audio [audioClip]- sound to play then object is collected
  4. Player - single entity table (meta), which store info about player
    1. gold [int]- amount of gold player gathered
    2. position [Vector3]- player's position, used by SaveLoad addon to save and load player's position
    3. rotation [Quaternion]- player's rotation, used by SaveLoad addon to save and load player's position
    4. scene [string]- player's scene, used by SaveLoad addon to save and load player's position

Save/Load settings

Let's look at the save/load setting to understand how they can be used to save/load your data during gameplay. You can find more information about Save/Load here

About Code Generation

We use code generation in this example (and we strongly recommend you to use it too). The long story short- instead of using basic API like this entity.Set("gold", entity.Get<int>("gold") +1)); code generation allows you to use code like this entity.gold=entity.gold+1;. As you can see code generation provides huge benefit, you can learn more about code generation here .

To distinct database fields from normal fields we use f_, m_ or d_ field prefixes in the examples below. We use all 3 types of code generation (for illustrative purpose), each prefix correspond to code generation type:

  1. BGM_ClassName and m_FieldName - MonoBehaviour generated classes (generated classes extends from MonoBehaviour and can be attached to GameObject)
  2. BGE_ClassName and f_FieldName - Extension classes (instead of creating basic BGEntity class, the database populated with classes which inherited from BGEntity and have all additional properties for all fields)
  3. BGD_ClassName and d_FieldName - Dna generated classes (this is a special case and can be avoided)

Code explanation

Some non relevant code is omitted.

  1. BGCollectable.cs- This script is attached to every collectable object. This script is hooked to a database by extending from BGM_Collectable class (generated by code generator), which in turn is extended from BGEntityGo- our component we use to connect GameObjects to database. When new collectable object is spawned in the scene by BGSpawner.cs, Entity field is assigned- and object become linked to a particular table row.
    This script has 4 tasks:
    1. Show gold amount on the TextMesh component. This is done by this code Text.text = "Gold:" + m_gold;. m_gold field reads/write data from/to database
    2. Add some gold to the player
    3. Play sound effect when object's collected.
    4. Remove the object when it's collected from scene and from database.
    public class BGCollectable : BGM_Collectable
    {
        //this callback is called then connected entity is changed
        public override void EntityChanged()
        {
            Text.text = "Gold:" + m_gold;
        }
    
        private void OnTriggerEnter(Collider other)
        {
            if (other.gameObject.CompareTag("Player"))
            {
                var player = other.GetComponent<BGPlayer>();
    
                //add gold
                player.m_gold += m_gold;
    
                //play sound
                var audioSource = player.GetComponent<AudioSource>();
                audioSource.clip = m_type.f_audio;
                audioSource.Play();
    
                //remove from database & scene
                Entity.Delete();
                Destroy(gameObject);
            }
        }
    }
            
  2. BGGoToScene.cs- this script is attached to a portal to another scene. When the player collides with this portal, he's moved to another scene. This script is also hooked up to a database, namely to Scene row, pointing to a scene to load. When the player collides with this object, script read data about this scene from database, updates Player table with position and rotation from Scene table and loads target scene.
    public class BGGoToScene : BGM_Scene
    {
        private void OnTriggerEnter(Collider other)
        {
            if (other.gameObject.CompareTag("Player"))
            {
                //get reference to player
                var player = other.GetComponent<BGPlayer>();
    
                //set player position & rotation to scene's spawn position & rotation
                player.m_position = m_spawnPosition;
                player.m_rotation = Quaternion.Euler(m_spawnRotation);
    
                //load the scene
                SceneManager.LoadScene(Entity.Name);
            }
        }
    }
            
  3. BGSpawner.cs- this script fills database with new objects and also spawn them to the scene. It hooked up to Scene table. It uses database events, to find the moment all objects are collected.
    public class BGSpawner :BGM_Scene
    {
        public override void  Start()
        {
            base.Start();
            Spawn();
            //use database events to keep track the moment, when all collectables are gathered
            BGRepo.I.Events.AddAnyEntityDeletedListener(BGE_Collectable.MetaDefault.Id, CheckForNewSpawns);
        }
    
        public override void OnDestroy()
        {
            base.OnDestroy();
            BGRepo.I.Events.RemoveAnyEntityDeletedListener(BGE_Collectable.MetaDefault.Id, CheckForNewSpawns);
        }
    
        //spawn unity's gameobjects - corresponding to Repo objects
        private void Spawn()
        {
            //fetch collectables from database
            var collectables = m_Collectable;
    
            //no collectables- no luck
            if (BGUtil.IsEmpty(collectables)) return;
    
            //spawn collectables objects
            foreach (BGEntity collectable in collectables)
            {
                //create collectable GameObject
                var newCollectable = Instantiate(collectable.f_type.f_prefab,
                    collectable.f_position, Quaternion.identity);
    
                //we know - collectable prefab has BGCollectable script attached - so hook it up to table's row
                newCollectable.GetComponent<BGCollectable>().Entity = collectable;
            }
        }
    
        //This method create new collectables randomly for all scenes if all objects are collected
        public void CheckForNewSpawns(object sender, BGEventArgsAnyEntity args)
        {
            //there are still some collectables
            if (BGE_Collectable.CountEntities > 0) return;
    
            //ok, we gathered all objects- lets spawn new ones
            BGE_Scene.ForEachEntity(scene =>
            {
    
                //number of collectables for one scene
                var count = Random.Range(3, 6);
                for (var i = 0; i < count; i++)
                {
                    //nested meta has utility method, which auto assign new collectable to owner entity (scene)
                    var newCollectable = BGE_Collectable.NewEntity(scene);
    
                    //set gold
                    newCollectable.f_gold = Random.Range(1, 10);
    
                    //bounds determines scene's frontiers
                    var bounds = scene.f_bounds;
                    //set position
                    newCollectable.f_position = new Vector3(Random.Range(bounds.min.x, bounds.max.x),
                        bounds.center.y, Random.Range(bounds.min.z, bounds.max.z));
    
                    //set type
                    newCollectable.f_type = BGE_CollectableType.GetEntity(Random.Range(0, BGE_CollectableType.CountEntities));
                }
            });
    
            //spawn GameObjects for current scene
            Spawn();
        }
    }
            
  4. BGPlayer.cs- this script is attached to the player and hooked up to a first row of Player table via extending from BGM_Player.
    1. It initialize it's position and rotation from database in the Start method
    2. It implements BGAddonSaveLoad.BeforeSaveReciever interface to ensure OnBeforeSave method is called before saving. In this method it saves it's own position and amount of gold to the database, so while saving those values will be put to the save file.
    public class BGPlayer : BGM_Player, BGAddonSaveLoad.BeforeSaveReciever
    {
        public override void Start()
        {
            base.Start();
            //get pos and rotation from the table
            transform.position = m_position;
            transform.rotation = m_rotation;
        }
    
        //this method is called before saving
        void BGAddonSaveLoad.BeforeSaveReciever.OnBeforeSave()
        {
            //save current position, rotation and scene to the database
            m_position = transform.position;
            m_rotation = transform.rotation;
            m_scene = BGE_Scene.FindEntity(scene => string.Equals(scene.Name, SceneManager.GetActiveScene().name));
        }
    }
            
  5. BGSavingLoading.cs It Provides Save/Load functions via SaveLoad addon. More information about Save/Load addon can be found here
    public class BGSavingLoading : MonoBehaviour
    {
        //... some code is omitted
        public void Save()
        {
            //save
            var bytes = BGRepo.I.Addons.Get<BGAddonSaveLoad>().Save();
            File.WriteAllBytes(SaveFilePath, bytes);
        }
    
        public void Load()
        {
            //load
            if (!HasSavedFile) return;
    
            var content = File.ReadAllBytes(SaveFilePath);
    
            BGRepo.I.Addons.Get<BGAddonSaveLoad>().Load(content);
    
            //load saved scene
            SceneManager.LoadScene(R.Player.d_scene.Get(PlayerEntity).Name);
        }
    }