【Unity】各データ保存形式の特徴と、ケース別に見るマスターデータ管理技術の選定

# 最初に

本記事は、**PlayerPrefs**をはじめとする各種保存形式の情報と使いどころをまとめた内容となります。Unityでデータ保存を考える際には、さまざまな形式や手法が選べるため、それぞれのメリット・デメリットを考慮し、プロジェクト規模と用途に合わせて最適な形式を選ぶ必要があります。この記事が、データ保存方法の選定の一助となれば幸いです。

本記事の対象者は以下の方を想定しています：

- Unity初心者で、データ保存の基本を学びたい方
- PlayerPrefs以外の選択肢を知りたい方
- 各種保存形式をどのように使い分ければいいのか悩んでいる方

### 環境

- **Unityバージョン**：Unity 6000.0.27f1

<br>

# 各データ保存形式の特徴

Unityを使用したプロジェクトで、一時データ、マスターデータ、ゲーム進行状況、ユーザー設定などのデータを管理・保存するには、以下の形式が候補に挙がります。

- **PlayerPrefs**：Unityに組み込まれた軽量な保存形式
- **ScriptableObject**：静的データ管理に特化したUnity独自の形式
- **JSON**：広く使われるテキスト形式で、階層構造に対応
- **CSV**：フラットなデータ構造に適した形式で、外部ツールとの親和性が高い
- **XML**：階層データを扱えるが、JSONに比べて冗長
- **Firestore**：クラウドベースのNoSQLデータベースで、リアルタイム同期をサポート
- **FirebaseのRealtime Database**：Firestoreの前身で、簡易なリアルタイムデータ同期向け
- **MasterMemory**：Unityに特化した高速な読み取り専用データ管理ライブラリ

これらの形式には、それぞれ向き・不向きな場面があります。特徴を踏まえた上で、どの形式を採用するのか考える必要があります。

<br>

## 1. PlayerPrefs

PlayerPrefsは、Unityが標準で提供するシンプルなデータ保存機能です。

主に**設定データや進行状況の保存**に使用され、小規模なプロジェクトや単純なデータ管理に適しています。サーバーとの通信を必要としない場合や、セキュリティの重要度が低い用途に利用される一方で、大量のデータや、複雑なデータ構造が求められる場合には不向きです。

### 用途と適用シーン

- **音量や画質の設定保存**（例：`Volume = 0.8`）
- **進行状況のフラグ管理**（例：チュートリアル完了状態）
- **ログイン情報の一時保存**（例：トークンやユーザーID）

### メリット

- **シンプルなAPI**：短いコードで簡単にデータ保存が可能
- **クロスプラットフォーム対応**：AndroidやiOSなど、複数プラットフォームで利用可能
- **軽量な用途に最適**：設定データや進行状況の簡易保存に向いてる
- **永続性**：アプリ終了後もデータが保持される

### デメリット

- **パフォーマンスの低下**：保存するデータ量が増えると保存やロードが遅くなる可能性あり（数百件以上は非推奨）
- **デバッグが面倒**：データの確認や編集には外部ツールが必要
- **複雑なデータ構造に非対応**：配列やオブジェクトを保存する場合は、JSONなどを利用して文字列として保存する必要がある

### 保存形式

PlayerPrefsは**キー・バリュー形式**でデータを保存します。

サポートする型は以下の3種類です：

- 整数 (`SetInt`, `GetInt`)
- 浮動小数点数 (`SetFloat`, `GetFloat`)
- 文字列 (`SetString`, `GetString`)

**書き込み例**：

```csharp
// 音量を保存
PlayerPrefs.SetFloat("Volume", 0.5f);

// ハイスコアを保存
PlayerPrefs.SetInt("HighScore", 1000);

// チュートリアル完了フラグを保存
PlayerPrefs.SetString("TutorialComplete", "true");

// 変更を即座に反映（推奨されるが省略可能）
PlayerPrefs.Save();
```

**読み込み例**：

```csharp
// 音量を取得（デフォルト値は0.5f）
float volume = PlayerPrefs.GetFloat("Volume", 0.5f);

// ハイスコアを取得（デフォルト値は0）
int highScore = PlayerPrefs.GetInt("HighScore", 0);

// チュートリアル完了フラグを取得（デフォルト値は"false"）
string tutorialComplete = PlayerPrefs.GetString("TutorialComplete", "false");
```

<br>

## 2. ScriptableObject

ScriptableObjectは、Unityが提供する軽量なデータ保存形式です。

主に**共用するデータや定数の管理**に適しており、Unityエディタ内で視覚的にデータを管理できます。データを複数のシーンやゲームオブジェクトで共有可能で、ゲームバランスの調整や定義済みのリソースの再利用に特化しています。

### 用途と適用シーン

- **ゲーム内定数や共用するデータの保存**（例：キャラクターステータス、武器データ）
- **設定ファイルの管理**（例：ゲームバランスパラメータ、グローバル設定）
- **リソースの共有管理**（例：複数シーンで使用される共有データ）
- **プロトタイプの素早い調整**（例：仮データでのスピーディな実装）

### メリット

- **視覚的な管理**：Unityエディタ上で直感的にデータの作成・編集が可能
- **データの再利用**：単一のデータを複数のゲームオブジェクトで共有可能
- **パフォーマンスに優れる**：データはアセットとして保存され、メモリ効率が高い
- **Unityプロジェクト内での管理に最適**：Unityプロジェクト内へ統合されているため、外部ツールを必要としない

### デメリット

- **ランタイムでの永続化に非対応**：データの保存や変更はエディタ内でのみ可能で、ランタイム時には別の保存形式が必要
- **外部ツールとの連携が難しい**：データ形式がUnity専用であり、他のアプリケーション（例：Excel）とのやり取りには工夫が必要
- **複雑な構造には不向き**：シンプルなデータ管理には適しているが、複雑なデータ構造を扱う場合は不向き

### 保存形式

ScriptableObjectは、Unityプロジェクト内の**アセット**として保存されます。コードで定義した構造体に基づき、Unityエディタ上でデータを作成・編集します。

**例（ScriptableObjectの定義とデータ構造）**：

```csharp
using UnityEngine;

[CreateAssetMenu(fileName = "NewWeapon", menuName = "ScriptableObjects/Weapon", order = 1)]
public class Weapon : ScriptableObject
{
    public string WeaponName;
    public int AttackPower;
    public Sprite Icon;
}

```

<br>

## 3. JSON

**JSON (JavaScript Object Notation)** は、構造化データを保存するための形式として広く利用されています。**階層構造**を持つデータの保存や読み書きが可能で、Unityでは主に設定データや進行状況、キャラクターデータなどを保存する際に活用されます。サーバーとデータをやり取りする際のフォーマットとしても一般的です。

### 用途と適用シーン

- **設定データの保存**（例：音量、画質、言語設定）
- **ゲーム進行状況やキャラクターデータの管理**（例：現在のレベル、スコア、アイテム）
- **サーバーとやり取りするデータのフォーマット**（API通信におけるリクエスト/レスポンスデータ）

### メリット

- **階層構造のサポート**：オブジェクトや配列を含む複雑なデータ構造を管理可能
- **デバッグの容易さ**：データが人間に読みやすい形式で保存される
- **柔軟性**：ネストされたデータの表現が可能で、幅広い用途に対応
- **汎用性**：サーバー通信や他のシステムとの連携に適している

### デメリット

- **処理速度**：MessagePackのようなバイナリ形式に比べると、読み書きに時間がかかる
- **ファイルサイズ**：テキストベースのため、バイナリ形式に比べてサイズが大きくなる
- **追加ライブラリが必要な場合がある**：複雑なJSON処理には、Newtonsoft.Jsonなどのサードパーティ製ライブラリが便利だが、その利用には導入・セットアップの手間が必要

### 保存形式

JSONはテキスト形式で保存され、オブジェクトや配列を階層的に表現できます。Unityの**JsonUtility**を使用すれば、オブジェクトのシリアライズ/デシリアライズも簡単に行えます。

**例（データ構造のテキスト表現）**：

```json
{
  "PlayerName": "Alice",
  "Level": 5,
  "Inventory": [
    {"ItemID": 101, "Quantity": 1},
    {"ItemID": 202, "Quantity": 5}
  ]
}

```

<br>

## 4. CSV

**CSV (Comma-Separated Values)** は、データをカンマ区切りで記録する形式です。

テキスト形式でデータを簡単に保存・共有できるため、ランキングや統計データなど、**フラットなデータ構造**を扱う用途で広く利用されています。特に、**外部ツール（ExcelやGoogle Sheets）との互換性**が高いため、ゲーム開発プロジェクトではマスターデータを外部ツールで定義した上で、それを実際のUnityへ共有場面でエクスポート形式として活躍します。

### 用途と適用シーン

- **ランキングデータの保存**（例：プレイヤー名、スコア、順位）
- **統計データの保存**（例：プレイセッションログ、スコア履歴）
- **外部ツールとのデータ共有**（例：ゲームデザイナーが作成したパラメータをゲームに取り込む）
- **シンプルな設定管理**（例：簡単なリストデータ）

### メリット

- **シンプルで軽量**：構造が単純で、データの書き込み・読み込みが高速
- **汎用性**：ほぼすべてのプログラミング言語とツールで扱える形式
- **外部ツールとの親和性**：ExcelやGoogle Sheetsでの編集が容易
- **可読性**：テキスト形式で保存されるため、人間が直接編集しやすい

### デメリット

- **階層構造に非対応**：データがフラットなリスト形式に限定されるため、複雑なデータ構造を扱えない
- **データ管理の煩雑さ**：列や行の数が多くなると管理が難しくなる
- **データ整合性の保証が難しい**：CSVでは列の型や制約を定義できないため、誤ったデータが混入しやすい
- **エスケープ処理の必要性**: データ内にカンマや改行が含まれる場合、適切にエスケープしないと読み書きエラーが発生する

### 保存形式

CSVでは、データをカンマ（`,` ）で区切り、1行に1レコードを記録します。

データにカンマや改行が含まれる場合は、ダブルクオートで囲む必要があります。

**フォーマット例**：

```
PlayerName,Score,Rank
Alice,1200,1
Bob,950,2
Charlie,870,3
```

<br>

## 5. XML

**XML (eXtensible Markup Language)** は、階層構造を持つデータをタグ形式で記述する柔軟なデータ保存形式です。JSONと同様に階層データを扱えますが、**タグ形式**で表現されるため、可読性と表現力が高い一方で、ファイルサイズが大きくなる傾向があります。

### 用途と適用シーン

- **設定データの保存**（例：ゲームオプション、キャラクターデータ）
- **階層構造を持つデータの保存**（例：アイテムリストやスキルツリー）
- **他のシステムとのデータ連携**（例：外部ツールやAPIとのデータ交換）
- **長期間保管が必要なデータの保存**（例：保存データのアーカイブ）

### メリット

- **階層構造のサポート**：ネストされたデータ構造をタグ形式でわかりやすく記述可能
- **可読性**：タグベースの形式で、データ構造が直感的に理解しやすい
- **汎用性**：JSONに比べてタグ形式の柔軟性が高く、ドキュメント形式のデータにも対応可能
- **データ型や制約の記述**：XMLスキーマを用いることで、データ型や構造のルールを設定可能

### デメリット

- **冗長性**：タグ形式でデータを記述するため、ファイルサイズが大きくなりやすい
- **処理速度**：JSONやMasterMemoryよりも読み書きの速度が遅い
- **編集の煩雑さ**：深い階層構造を持つデータは、人間が直接編集する際、煩雑になりやすい
- **デバッグの手間**：パースエラーが発生した場合、原因特定が難しいことがある

### 保存形式

XMLはタグを使ってデータを記述します。

データが階層的に構造化されるため、複雑なデータの保存に適しています。

**例（テキスト表現）**：

```xml
<PlayerData>
  <PlayerName>Alice</PlayerName>
  <Level>5</Level>
  <Inventory>
    <Item ItemID="101" Quantity="1" />
    <Item ItemID="202" Quantity="5" />
  </Inventory>
</PlayerData>
```

<br>

## 6. Firestore

**Firestore (Cloud Firestore)** は、Googleが提供するクラウド型のNoSQLデータベースです。

リアルタイムデータ同期や階層構造データの保存が可能で、モバイルアプリやゲーム開発で特に利用されています。サーバーレスで効率的にデータを管理・共有できるため、多人数参加型のゲームやリアルタイム性が求められるアプリケーションに最適です。

### 用途と適用シーン

- **ユーザーデータの保存**（例：プロフィール、ゲーム進行状況）
- **ランキングやスコアボードの管理**（例：全ユーザーのハイスコアをリアルタイムで共有）
- **リアルタイムチャットや通知の管理**（例：メッセージの即時送受信）
- **ゲーム内設定やリモートデータの管理**（例：ゲームのパラメータ調整をサーバー側で変更）

### メリット

- **リアルタイム同期**：複数クライアント間でのデータ更新を即座に共有可能
- **階層構造のサポート**：ドキュメント/コレクション形式で複雑なデータを管理可能
- **スケーラビリティ**：Googleインフラにより、小規模から大規模なアプリまで対応
- **オフラインサポート**：ローカルキャッシュ機能により、ネットワーク接続がなくてもデータを利用可能
- **管理の容易さ**：Firebaseコンソールからデータの可視化と編集が可能

### デメリット

- **コスト**：課金モデルが読み書き回数やデータ量に依存しており、頻繁にアクセスするアプリではコストが増加する可能性がある
- **遅延の可能性**：リアルタイム性は高いものの、ネットワーク状況やリクエスト量によっては遅延が発生する場合がある
- **学習コスト**：クエリ構築やセキュリティルール設定に一定の技術的知識が必要
- **ネットワーク依存性**：一部操作にはネットワーク接続が必須で、完全なオフライン動作は難しい

### 保存形式

Firestoreでは、データを**ドキュメント/コレクション**という形式で保存します。

- **ドキュメント**：JSON形式の単位データ（キー・バリューの組み合わせ）
- **コレクション**：ドキュメントの集合

**例（Firestoreの保存形式）**：

```json
/Users (コレクション)
  /User123 (ドキュメント)
    {
      "Name": "Alice",
      "Score": 1500,
      "Items": [
        { "ItemID": 101, "Quantity": 1 },
        { "ItemID": 202, "Quantity": 3 }
      ]
    }
```

<br>

## 7. Realtime Database (Firebase)

**Realtime Database**は、Firebaseが提供するクラウド型NoSQLデータベースデータベースで、データを**JSON形式**で保存し、高性能なリアルタイム同期を提供します。

Firestoreの前身とも言えるサービスで、現在でも**軽量かつリアルタイム性が必要な小規模アプリケーションやゲーム**で広く利用されています。

### Firestoreとの違い

| 特徴 | **Realtime Database** | **Firestore** |
| --- | --- | --- |
| データ形式 | JSON形式 | ドキュメント/コレクション形式 |
| リアルタイム同期の性能 | 非常に高い（リアルタイム用途に特化）    | 高い（柔軟性があるが若干劣る）  |
| クエリ機能 | シンプル（複雑な条件の検索には不向き）    | 高度なクエリが可能 |
| スケーラビリティ | 中規模向け（データ量が増えるとパフォーマンスが低下）  | 小〜大規模向け |
| コスト | 安価（ただしデータ転送量が増えると増加しやすい） | コスパ良き（複雑なクエリにも対応可能） |

### 用途と適用シーン

- **リアルタイム同期が必要な機能の実装**（例：チャットアプリ、スコアボード）
- **階層構造を持つデータの保存**（例：プレイヤーデータやゲーム進行状況）
- **設定やリモートデータの管理**（例：リモートコンフィグのデータ）
- **小規模なリアルタイムアプリケーション**

### メリット

- **リアルタイム同期**：すべてのクライアント間で即時にデータを反映。リアルタイム性が求められる機能に最適
- **シンプルなAPI**：初心者でも簡単にデータ読み書きを実装可能
- **オフライン対応**：ネットワーク接続がない場合でもローカルキャッシュにより動作を維持し、再接続時に同期
- **スケーラビリティ**：小〜中規模アプリケーションには十分対応可能

### デメリット

- **データ構造の制限**：深い階層のデータは管理が複雑になり、パフォーマンスの低下を招く可能性がある
- **クエリ機能の制約**：Firestoreに比べてクエリ機能が弱く、複雑な条件検索には不向き
- **コスト**：データ転送量に比例して課金されるため、大量のデータ同期が発生する場合はコストが増大する可能性がある

### 保存形式

Realtime Databaseは**JSON形式**でデータを保存します。階層構造をそのまま保持でき、簡単にデータのネストが可能です。

**例（Realtime Databaseの保存形式）**：

```json
{
  "Users": {
    "User123": {
      "Name": "Alice",
      "Score": 1500,
      "Items": [
        { "ItemID": 101, "Quantity": 1 },
        { "ItemID": 202, "Quantity": 3 }
      ]
    },
    "User456": {
      "Name": "Bob",
      "Score": 900
    }
  }
}
```

<br>

## 8. MasterMemory

**MasterMemory** は、Unityに特化した高速かつ軽量なデータ管理ライブラリで、読み取り専用のデータ管理を得意とします。

特にゲーム開発において、**マスターデータ（武器ステータス、ステージ情報など）の管理と検索を効率化**する目的で利用されます。データを事前にインデックス化することで、パフォーマンスに優れた動作を提供しています。

### 用途と適用シーン

- **ゲーム内の静的データの管理**（例：ステージデータ、武器やアイテムのステータス）
- **テンプレートデータの参照**（例：クラフトレシピ、敵のパラメータ設定）
- **複雑なデータ検索の高速化**（例：特定条件に基づくデータの取得）

### **メリット**

- **高速な検索**：事前にインデックス化されたデータにより、大量データでも短時間でクエリ処理が可能
- **低メモリ消費**：データはバイナリ形式で保持され、効率的にメモリを使用
- **型安全なデータ操作**：C#の型システムを活用して、ランタイムエラーを防止
- **静的データに特化**：変更が不要なマスターデータ（武器やステージ情報）に特化

### **デメリット**

- **読み取り専用**：読み取り専用設計のため、動的なデータ更新には不向き
- **デバッグの難しさ**：バイナリ形式で保存されるため、データの中身を直接確認するのが難しい
- **事前準備が必要**：CSVやスプレッドシートからの変換工程が必要で、準備に時間がかかる

### 保存形式

MasterMemoryは、**静的なバイナリ形式**でデータを保存します。事前にスプレッドシートやCSVからデータを変換し、インデックスを付加することで、検索性能を最適化しています。この形式により、クエリ操作が非常に高速で実行可能です。

**例（データ構造）**：

```csharp
[MemoryTable("Weapons")]
public class Weapon
{
    [PrimaryKey]
    public int WeaponId { get; set; }
    public string Name { get; set; }
    public int AttackPower { get; set; }
    public int MaterialCost { get; set; }
}
```

**例（MasterMemory利用コード）**：

```csharp
var weapon = memoryDb.Weapons.FindByPrimaryKey(101);
Debug.Log($"Weapon Name: {weapon.Name}, Attack: {weapon.AttackPower}");
```

<br>

# 保存形式の比較

一通り、メジャーな保存形式の特徴などを確認しました。

量が多いので、比較表を用意してみました。

| **データ保存形式** | **用途の汎用性** | **柔軟性** | **ランタイム編集** | **パフォーマンス** | **デバッグのしやすさ** | **セキュリティ** |
| --- | --- | --- | --- | --- | --- | --- |
| **PlayerPrefs** | △<br>（小規模データに限定） | △<br>（シンプルなキー・バリュー形式に限定） | ◎ | ◎<br>（小規模データで高速） | △<br>（外部ツールが必要） | ✕<br>（平文保存のため改ざんリスクあり） |
| **ScriptableObject** | △<br>（静的データに限定） | △<br>（Unity依存） | ✕<br>（ランタイムでの永続化不可） | ◎<br>（メモリ効率が良い） | ◎<br>（Unityエディタで直接編集） | △<br>（外部ツールへの連携は制約あり） |
| **JSON** | ◎<br>（設定データや階層構造データに対応） | ◎<br>（柔軟な階層構造対応） | ◎ | ○ | ◎<br>（テキストで確認可能） | ✕ |
| **CSV** | △<br>（フラットデータの保存に限定） | △<br>（階層データには不向き） | ◎ | ○ | ◎<br>（Excelやエディタで確認可能） | ✕ |
| **XML** | △<br>（冗長性が高いが階層対応） | ◎<br>（複雑なデータ構造に対応） | ◎ | ✕<br>（パースに時間がかかるため低速） | ◎<br>（テキストで確認可能） | ✕ |
| **Firestore** | ◎<br>（スケーラブルな動的データ管理） | ◎<br>（階層構造対応のドキュメント形式） | ○<br>（サーバー通信必須） | ◎<br>（スケーラブルで高速） | ◎<br>（コンソールで可視化） | ◎<br>（サーバー管理で安全） |
| **Realtime Database** | ◎<br>（リアルタイムデータ向け） | △<br>（シンプルなJSON形式） | ○<br>（サーバー通信必須） | ◎<br>（非常に高速） | ◎<br>（コンソールで可視化） | ◎<br>（サーバー管理で安全） |
| **MasterMemory** | ◎<br>（静的データ向けで高速） | △<br>（バイナリ形式依存） | ✕<br>（読み取り専用） | ◎<br>（事前インデックス化で非常に高速） | △<br>（専用ツールが必要） | ◎<br>（暗号化・署名で補強可） |

<br>

# おすすめ構成

次に、プロジェクト規模に応じてどの保存形式を採択していけば良さそうか、おすすめ構成を述べます。実際にはプロジェクトの具体的な要件に応じて選定を行う必要がありますが、参考資料として役立てば嬉しいです。

## 例１：小規模のソロプレイ専用カジュアルゲーム

### マスターデータ管理

- **保存形式：ScriptableObject**
- **理由**：クライアントのみで完結可能。Unityエディタ上でデータを直接管理・編集できる
- **データ例**：ステージ情報（レベル数、敵数、制限時間など）、UI設定データ
- **運用フロー：**
    1. データ作成：UnityエディタでScriptableObjectを作成し、データを編集
    2. 管理とビルド：作成したScriptableObjectをAddressableに登録してアセットバンドル化
    3. 使用：ビルド時にアセットを含め、ゲーム内でロードして使用

### サーバーとやり取りするデータ

- **保存形式：DB + Json**
- **理由**：JSONはシンプルで軽量なデータ交換フォーマットであり、パースが容易で動的なデータ同期に適している
- **データ例**：リーダーボード情報（スコア、順位）、イベント設定データ
- **運用フロー**：
    1. データベース構築：データベース（例：MySQL、PostgreSQL、MongoDB）の用意
    2. データ取得：HTTPリクエストを使用してJSON形式のデータをサーバーから取得
    3. データ処理：JsonUtilityや外部ライブラリを使ってデータをパース
    4. 使用：ローカル変数で管理し、ゲームに反映

### クライアント側で完結するデータ

- **保存形式：PlayerPrefs**
- **理由**：設定値の保存や進行状況管理など、小規模でシンプルな用途に最適
- **データ例**：音量設定、最終ステージ到達状況
- **運用フロー**：
    1. 保存：設定画面やゲーム進行に応じて、`PlayerPrefs.SetFloat`や`PlayerPrefs.SetInt`などを用いてデータを保存
    2. 使用：ゲーム開始時や設定画面のロード時に`PlayerPrefs.GetFloat`や`PlayerPrefs.GetInt`を使用してデータを読み出し、反映

<br>

## 例２：スマートフォンソーシャル2Dカードゲーム

### マスターデータ管理

- **保存形式**：スプレッドシート (または Excel) + CSV + MasterMemory
- **理由**：大量のデータ検索が効率的で、静的データの管理に特化している
- **データ例**：ステージデータ、アイテム情報、スキルツリー
- **運用フロー**：
    1. データ作成：スプレッドシートやExcelでマスターデータを作成
    2. データ変換：CSV形式でエクスポートし、MasterMemory形式に変換
    3. 管理とビルド：MasterMemoryファイルをAddressableに登録してアセットバンドル化
    4. 使用：ランタイムでデータをロードし、型安全な検索APIを利用して参照

### サーバーとやり取りするデータ

- **保存形式**：Firestore
- **理由**：動的なデータ管理に優れ、リアルタイム性が必要なソーシャル機能に適している
- **データ例**：プレイヤーのプロファイル、ランキングデータ
- **運用フロー**：
    1. データベース構築： Firestoreでデータベースを用意し、コレクションやドキュメントを設定
    2. データ取得：UnityのFirebase SDKを使用してFirestoreにクエリを送信し、必要なデータを取得
    3. データ処理：取得したデータをローカル変数や定義済みのクラスに格納
    4. 使用：データをUIやゲームロジックに適用

### クライアント側で完結するデータ

- **保存形式**：**PlayerPrefs**
- **理由**：ユーザー設定やデバイスに依存するデータの保存に最適
- **データ例**：ユーザー設定（グラフィッククオリティ、音量）
- **運用フロー**：
    1. 保存：設定画面やゲーム進行に応じて、`PlayerPrefs.SetFloat`や`PlayerPrefs.SetInt`などを用いてデータを保存
    2. 使用：ゲーム開始時や設定画面のロード時に`PlayerPrefs.GetFloat`や`PlayerPrefs.GetInt`を使用してデータを読み出し、反映

<br>

## 例３：クロスプラットフォーム向けマルチプレイサバイバルゲーム

### マスターデータ管理

- **保存形式**：スプレッドシート (または Excel) + CSV + MasterMemory
- **理由**：大量のデータ検索が効率的で、静的データの管理に特化している
- **データ例**：武器データ、クラフトレシピ、マップ情報
- **運用フロー**：
    1. データ作成：スプレッドシートやExcelでマスターデータを作成
    2. データ変換：CSV形式でエクスポートし、MasterMemory形式に変換
    3. 管理とビルド：MasterMemoryファイルをAddressableに登録してアセットバンドル化
    4. 使用：ランタイムでデータをロードし、型安全な検索APIを利用して参照

### サーバーとやり取りするデータ

- **保存形式**：Realtime Database
- **理由**：高速なリアルタイム同期が可能で、動的なゲームプレイデータに適している
- **データ例**：マッチメイキング情報、プレイヤー位置データ
- **運用フロー**：
    1. データベース構築：Realtime Databaseにデータ構造を設定し、必要なルールを設計
    2. データ接続：クライアントがFirebase SDKを使用してRealtime Databaseに接続
    3. データ同期：データ変更イベントをリッスンして、ゲームロジックにリアルタイムで反映
    4. データ更新：必要に応じてプレイヤーデータやゲーム状態をサーバーに更新

### クライアント側で完結するデータ

- **保存形式**：**ScriptableObject + JSON**
- **理由**：ScriptableObjectは定数データ、JSONは設定値や進行状況に適用
- **データ例**：ゲーム内設定値、ユーザーの進行状況
- **運用フロー**：
    1. 定数データ管理： ScriptableObjectをUnityエディタ内で作成・保持
    2. 進行状況の保存： ユーザー進行状況をJSON形式でローカルに保存
    3. データ読み書き： 自前のシステムでJSONファイルを保存・読み込みし、ゲームに反映

<br>

# まとめ

Unityでのデータ保存形式の選択は、**プロジェクトの規模**や**用途**に応じて柔軟に対応する必要があります。本記事では8つの主要な保存形式について解説し、さらに規模別のおすすめ構成を提示しました。

以下に、保存形式選定の際に覚えておきたいポイントをまとめます。

### **1. 規模に応じた柔軟な設計**

- 小規模プロジェクトでは、**ScriptableObject**や**PlayerPrefs**
- 中規模プロジェクトでは、**MasterMemory**や**Firestore**
- 大規模プロジェクトでは、**Realtime Database**や**MasterMemory**

### **2. 保存形式の選択基準**

- **静的データ**: 読み取り専用のマスターデータは、**MasterMemory**や**ScriptableObject**
- **動的データ**: リアルタイムに更新が必要なデータには、**Firestore**や**Realtime Database**
- **設定データ**: 小規模な設定データは、**PlayerPrefs**や**JSON**

### **3. マスターデータの管理とフロー**

スプレッドシートやExcelを活用してデータを作成し、それを適切な形式（**MasterMemory**や**CSV**など）に変換してUnity内で利用することで、データ管理と効率化を図ることができます。

### **4. セキュリティとパフォーマンスのバランス**

- **セキュリティを重視**するデータは、クライアントのみで管理せず、サーバーサイドで処理する設計が基本になると思います。
- **パフォーマンスを重視**する場合、検索が高速な形式（例: MasterMemory）を利用し、リアルタイム通信を最小限に抑えます。

この記事がプロジェクトに最適な保存形式を選び、効率的かつスケーラブルな設計を考える手助けになれば幸いです。