Unityでのセーブデータに悩んだ話と進捗報告

前書き

お久しぶりです
仕事忙しかったり、ゲームの仕組みの一部を作り直したりでなかなか更新できませんでした
あんまりネタがないので今回はTechな話をしたいと思います
あと、最後にちょっとだけ今のゲームの進捗貼ります

セーブデータの話

結論

SQLite使うようにした

今までと変えるに至った経緯

もともとはセーブデータは暗号化してMsgPackを用いて保存してました
採用理由はデシリアライズ速度でした

しかし、作っていった結果。。。。



細かいデータを保存したりするのに毎回デシリアライズ用のコード書くのめんどい!
ってなりました
まぁ、MsgPackのコンテナ系のデシリアライズの対応がいまいち悪いのも原因の一つです



作りずらいことこの上ないという状態でした


シームレスに大量のデータをリアルタイムで保存したいなー

DBみたいな仕組みあればいいなー

DBでいいじゃん

SQLiteがあるじゃん

といった感じで採用に至りました

実際の作り

大まかな部分はこちらの記事を参考にしています

UnityにSQLite-netを導入する


↑に加えてある程度のラッパーと自動生成する機構を作ったりしました


    <Entity>
        <Name>TestUser</Name>
        <Param>
            <Name>user_id</Name>
            <Type>uint</Type>
            <Primary>true</Primary>
            <Comment>ユーザーID</Comment>
        </Param>
        <Param>
            <Name>name</Name>
            <Type>string</Type>
            <Comment>name</Comment>
            <DefaultValue>Test</DefaultValue>
        </Param>
    </Entity>

こんなXMLを書くと

///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("TestUser")]
public class TestUserEntity
{
    /// <summary>
    /// ユーザーID
    /// <summary>
    [PrimaryKey]
    [Column("user_id")]
    public uint user_id { get; set; }
    /// <summary>
    /// name
    /// <summary>
    [Column("name")]
    public string name { get; set; }

}

public class TestUserModel
{
    private static bool Initialized = false;
    private static List<TestUserModel> items = null;

    public static IList<TestUserModel> Items
    {
        get
        {
            if(items == null)
            {
                GetAll();
            }
            return items;
        }
    }

    private TestUserEntity entity = new TestUserEntity();
    private CompositeDisposable disposable = new CompositeDisposable();
    
    public uint UserId => entity.user_id;
    private ReactiveProperty<string> name = new ReactiveProperty<string>();
    public IReadOnlyReactiveProperty<string> Name => name;

    


    public static async UniTask<TestUserModel> Get(uint user_id)
    {
        if (!Initialized)
        {
            await SaveDataCore.CreateTable<TestUserEntity>();
            Initialized = true;
        }
        
        if(items == null)
        {
            await GetAll();
        }
        
        if(items.Exists(i => i.UserId == user_id))
        {
            return items.First(i => i.UserId == user_id);
        }

        var entity = new TestUserEntity();
        entity.user_id = user_id;
        entity.name = Test;

        await SaveDataCore.InsertData(entity);
        var model = new TestUserModel(entity);
        items.Add(model);
        return model;
    }

    private static async UniTask GetAll()
    {
        if (!Initialized)
        { 
            await SaveDataCore.CreateTable<TestUserEntity>();
            Initialized = true;
        }

        if (items == null)
        {
            var datas = await SaveDataCore.GetAllData<TestUserEntity>();
            var models = new List<TestUserModel>();
            foreach (var data in datas)
            {
                models.Add(new TestUserModel(data));
            }
            items = models;
        }
    }

    private TestUserModel(TestUserEntity _entity)
    {
        entity = _entity;
        name.Value = entity.name;
        name.Do(v => entity.name = v).Subscribe(_ => UpdateData()).AddTo(disposable);

    }

    private async UniTask UpdateData()
    {
        await SaveDataCore.UpdateData(entity);
    }
     
    public void UpdateName(string _name)
    {
        name.Value = _name;
    }

    
    ~TestUserModel()
    {
        disposable.Dispose();
    }
}

こんなコードができます
どうやって作っているのといわれると、ある程度のテンプレートを作成してreplaceとstreingBuilderで頑張って作ってるって感じです
かなりゴリラな作り方なのである程度できる方ならわかっちゃうと思います

こんな感じセーブデータを保存するクラスをバンバン量産できるようにしてます

フラグ管理などもDBなのでいっぱいデータ作れる安心感が良いです


作ってるゲームの話

今作っている画面はこんな感じです
街中でのショップ機能とか作ってます
Gif


スクリーンショット



本来であればShop機能などが右側に乗るはずなので、こちらも少々お待ちを。。。。



小言
最初はランダム生成でキャラのバリエーション増やすつもりだったのですが、プチプチと作っていくうちに、ある程度ユニークなキャラがいたほうがいいなと思い至り↑のShop店員さんたちを作成することになりました

こうやっていろいろ作っちゃうと、ランダム生成キャラは汎用的なエロで済ませるつもりだったのが、ユニークなキャラには専用の何かを設けたくなってしまいますね。。。。

この記事が良かったらチップを贈って支援しましょう!

チップを贈るにはユーザー登録が必要です。チップについてはこちら

月別アーカイブ

限定特典から探す

記事を検索