原カバンは鞄のお店ではありません。

Unityを使ったゲーム制作のあれこれを綴っていきます。

【Unity】マスタデータの管理にMasterMemoryを使う(実装編)

聞いてない

東京五輪の時もそうでしたがSNS等で「私は万博には行きません」とわざわざ表明する進歩的文化人の方々の意図が良く分からない一般庶民の皆さんこんにちは。誰も別に聞いてないんですが。日本で大きなイベントが開催されると必ずと言っていいほど自己顕示欲を抑えきれないのか何なのか、そういった方々が雨後の公園のミミズのように這い出てきますが必要とされてないので静かにしておいてほしいものです。まぁ、私も行く気はないけど。

 

MasterMemory

前回の記事でUnityでのマスタデータを利用する手法として「MasterMemory」を紹介しました。

github.com

MasterMemoryはマスタデータのような静的な大量データを扱うのに長けていて、省メモリで高速な検索を可能にします。このアセットはCysharp社が開発したアセットですがライセンスの範囲内であれば誰でも自由に使う事ができます。

 

MasterMemoryを使用してデータを管理するにはデータが保存されたデータクラス(配列等)をバイナリデータへの変換が必要で、MasterMemoryはこの変換されたバイナリデータを使ったデータの検索や取得の処理を行います。

この為、MasterMemoryの導入にはバイナリデータに変換する処理とバイナリデータからデータを読み込む処理を実装したスクリプトが必要で、前回の記事ではその辺りの実例を紹介させてもらいました。

【Unity】マスタデータの管理にはMasterMemoryが便利(導入と仕組みについて)

 

前回からの続き

今回も以下のようなデータ構造のクラスを使用するとします。

// クラスにMemoryTableアトリビュートをつける
// クラスにMessagePackObjectアトリビュートをつける
[MemoryTable("Music"), MessagePackObject(true)]
public sealed class MusicData
{
	// プライマリキーにはPrimaryKeyアトリビュートをつける
	[PrimaryKey]
	public string Id { get; set; }

	public string MusicName { get; set; }

	public int MusicBPM { get; set; }

	public string PlayTime { get; set; }
}


前回の記事ではこのデータクラスを使ったマスタデータをスクリプト内部で定義していましたが、実際にゲーム内で使用する場合は別のファイルに外出して定義する方が便利なので、今回はJSON形式のデータを用意し、それを読み込んでデータクラスを定義したいと思います。

[
  {
    "Id": "00",
    "MusicName": "カラフルな生活",
    "MusicBPM": 110,
    "PlayTime": "01:35"
  },
  {
    "Id": "01",
    "MusicName": "散々なんだよ、この空は",
    "MusicBPM": 88,
    "PlayTime": "02:16"
  },
  {
    "Id": "02",
    "MusicName": "君はレトロ",
    "MusicBPM": 83,
    "PlayTime": "02:35"
  }
]

用意したJSON形式のデータファイル

 

ファイルの読み込みとビルド

JSON形式のファイルを読み込んでデータクラスへ設定するにはMessagePackのAPIを使用します。MessagePackは外部のアセットですがMasterMemoryを導入する際に併せてインストールされていると思うので特に設定を追加することなく使う事が出来ます。

using System;
using UnityEngine;
using MessagePack;

/// <summary>
/// Jsonファイル読み込みクラス
/// </summary>
public class JsonFileLoad
{
  ////////////////////////////////////
  ///     Jsonファイル読み込み     ///
  ////////////////////////////////////

  /// <summary>
  /// Jsonロード
  /// </summary>
  /// <typeparam name="T">取得するデータモデル</typeparam>
  /// <typeparam name="K">ファイル読み込み名</typeparam>
  /// <returns></returns>
  public static T[] JsonLoad<T>()
  {
    try
    {
      string downloadPath = $"Data/{typeof(T).Name}";
      string json = Resources.Load<TextAsset>(downloadPath).text;

      var bytes = MessagePackSerializer.ConvertFromJson(json);
      return MessagePackSerializer.Deserialize<T[]>(bytes);
    }
    catch (Exception)
    {
      throw;
    }
  }
}

上記のJsonファイル読み込みクラスを経由してDatabaseBuilderを使ってバイナリデータに変換してファイルに保存します。

using System.IO;
using MasterMemory;
using MessagePack;
using MessagePack.Resolvers;
using UnityEditor;

public static class BinaryGenerator 
{
	[MenuItem("Tools/Master/Generate Binary")]
	private static void Run()
	{
		// MessagePackの初期化(ボイラープレート)
		var messagePackResolvers = CompositeResolver.Create(
			MasterMemoryResolver.Instance, // 自動生成されたResolver
			StandardResolver.Instance // MessagePackの標準Resolver
		);

		var options = MessagePackSerializerOptions.Standard.WithResolver(messagePackResolvers);
		MessagePackSerializer.DefaultOptions = options;

		// DatabaseBuilderを使ってバイナリデータを生成する
		var databaseBuilder = new DatabaseBuilder();
		databaseBuilder.Append(JsonFileLoad.JsonLoad<MusicData>());
		var binary = databaseBuilder.Build();

		// バイナリのファイル保存
		var path = "Assets/Resources/Binary/MusicData.bytes";
		var directory = Path.GetDirectoryName(path);
		if (!Directory.Exists(directory)) Directory.CreateDirectory(directory);
		File.WriteAllBytes(path, binary);
		AssetDatabase.Refresh();
	}
}

このBinaryGeneratorがコンパイルされるとメニューのTool配下に「Master>Generate Binary」の項目が追加されるので、その項目を選択すると

Resources/BinaryディレクトリにMasterMemoryで使用するバイナリデータファイルが生成されます。

 

参照側はMemoryDatabaseに変換したバイナリデータを読み込み、そこから検索キーを指定した検索を行って目的のデータを取得します。(ここは前回と同じ)

var path = "Assets/Resources/Binary/MusicData.bytes";
var asset = AssetDatabase.LoadAssetAtPath<TextAsset>(path);
var binary = asset.bytes;

var memoryDatabase = new MemoryDatabase(binary);
var data = memoryDatabase.MusicDataTable.FindById("01");

 

最後に

データをJson形式で定義する事でデータを変更してもプロジェクトのコンパイルをする必要がなく、メニューから選ぶだけでバイナリデータの生成が行えるのでかなり使いやすくなったと思います。
ただ、上のBinaryGeneratorのクラスはエディタ拡張となるので、ゲームを実行形式にビルドする際には「#if UNITY_EDITOR」を定義するなどしてビルド対象から外す必要がある事に注意してください。

◇プライバシーポリシー

●個人情報の利用目的

当ブログでは、メールでのお問い合わせ、メールマガジンへの登録などの際に、名前(ハンドルネーム)、メールアドレス等の個人情報をご登録いただく場合がございます。

これらの個人情報は質問に対する回答や必要な情報を電子メールなどをでご連絡する場合に利用させていただくものであり、個人情報をご提供いただく際の目的以外では利用いたしません。

●個人情報の第三者への開示

当サイトでは、個人情報は適切に管理し、以下に該当する場合を除いて第三者に開示することはありません。

・本人のご了解がある場合
・法令等への協力のため、開示が必要となる場合

個人情報の開示、訂正、追加、削除、利用停止
ご本人からの個人データの開示、訂正、追加、削除、利用停止のご希望の場合には、ご本人であることを確認させていただいた上、速やかに対応させていただきます。

アクセス解析ツールについて

当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。

このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。このトラフィックデータは匿名で収集されており、個人を特定するものではありません。
この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。

●免責事項

当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。

当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。

当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

●プライバシーポリシーの変更について

当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。