概要
別名義で活動しているのでタイトルは伏せさせていただきますが、個人でインディーズゲームを作成しておりました
その際に作って便利だったUnityの拡張などの機能や仕組みの紹介をします
今回はSQLiteを用いたセーブデータ編となります
基本的には生成物や生成前のデータ、最低限のロジックなどは説明しますがコードは記載しません
自身で作成する際のヒントになればと思います
生成前のXML
生成されるC#コード
///Don't write
///This is Generated Code
using System;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using SQLite;
using UniRx;
[Table("GameData")]
public class GameDataEntity : EntityBase
{
/// <summary>
/// ユーザーID
/// <summary>
[PrimaryKey]
[Column("user_id")]
public int user_id { get; set; }
/// <summary>
/// 所持金
/// <summary>
[Column("money")]
public int money { get; set; }
}
public class GameDataModel
{
private static List<GameDataModel> items = null;
public static IList<GameDataModel> Items
{
get
{
if(items == null)
{
GetAll();
}
return items;
}
}
private GameDataEntity entity = new GameDataEntity();
private CompositeDisposable disposable = new CompositeDisposable();
public int UserId => entity.user_id;
private ReactiveProperty<int> money = new ReactiveProperty<int>();
public IReadOnlyReactiveProperty<int> Money => money;
public static async UniTask<GameDataModel> Get()
{
if(items == null)
{
await GetAll();
}
if(items.Exists(i => i.UserId == 0))
{
return items.First(i => i.UserId == 0);
}
var entity = new GameDataEntity();
entity.user_id = 0;
entity.money = default;
await SaveDataCore.InsertData(entity);
var model = new GameDataModel(entity);
items.Add(model);
return model;
}
private static async UniTask GetAll()
{
if (items == null)
{
var datas = await SaveDataCore.GetAllData<GameDataEntity>();
var models = new List<GameDataModel>();
foreach (var data in datas)
{
models.Add(new GameDataModel(data));
}
items = models;
}
}
private GameDataModel(GameDataEntity _entity)
{
entity = _entity;
money.Value = entity.money;
money.Do(v => entity.money = v).Subscribe(_ => UpdateData()).AddTo(disposable);
}
private async UniTask UpdateData()
{
await SaveDataCore.UpdateData(entity);
}
public void UpdateMoney(int _money)
{
money.Value = _money;
}
~GameDataModel()
{
disposable.Dispose();
}
}
使用技術
- XML
- C#
- System.Xml.Linq
- SQLite-net
- UniRX
- いずれR3に置き換える
となっております
- いずれR3に置き換える
こちらはC#のロジックにより作られているため、UniRX以外の部分はgodotエンジンに移植しても動作しました
↑のコード上ではSQLite-netがかなりラップされた状態のコードになってます
基本的にはTemprate用のTextファイルを用意して、文字を置き換えるような形で対応してます
自動生成の流れはこんな感じです
コンセプト
基本的にはXMLでセーブデータに関する機能が全部自動生成されるようにしたい
セーブデータを書き換えた場合は即保存したい
セーブデータの実データはDBのように扱いたい(デバックしやすくするため
これらの理由からSQLiteを採用しつつ↑のようなコードを自動生成する形となりました。
その他
↑の仕組みでは
マイグレーションについて触れてませんが、SQLite-netがかなりいい感じにやってくれます
SQLite-netが実際便利なので、SQLite側の機能はかなり甘えた仕組みになってます