スポンサーリンク
UnityUnityメモ

Unityのシリアライズ完全ガイド!データの保存・読み込みを自由自在に

Unity

Unityシリアライズ徹底解説|SerializeFieldとSerializableの使い方ガイド

はじめに

Unityでゲームを作っていると、「データを保存したい」「Inspectorから調整したいけど他のスクリプトからは触らせたくない」なんて思うこと、ありますよね。そんなときにカギになるのが シリアライズ(Serialization) という仕組みです。

シリアライズは、データを「バイト列」として保存・復元できるようにする仕組みのこと。ちょっと難しそうに聞こえるかもしれませんが、Unityではこの仕組みが当たり前のように動いていて、実は毎日触っているんです。たとえば、Inspectorで数値を入力したり、Prefabを保存したりするのもシリアライズのおかげなんですよ✨

この記事では、[SerializeField][Serializable] の違いや役割、さらに応用的なシリアライズの使い方までを徹底解説します。初心者さんでもイメージしやすいように、コード例を交えながらわかりやすくまとめました。もちろん、中級者や上級者の方にも「そうそう、これ便利!」と思える小技も紹介していきます。

さらに、データ保存をもっと簡単にしてくれるアセットや、Inspectorを強化して効率的に開発できるツールもあわせて紹介しますので、「Unityで効率よく開発したい!」という方はぜひ参考にしてくださいね。




シリアライズとは?基礎解説

まずは基本から。シリアライズ(Serialization)とは、オブジェクトや変数の状態を「保存できる形式」に変換することを指します。変換後のデータはファイルやデータベースに保存でき、必要に応じて元の状態に復元(デシリアライズ)できます。

Unityでは、この仕組みがゲームのさまざまな場面で使われています。例えば…

  • Inspectorに表示される数値やチェックボックス
  • Prefabやシーンデータの保存と復元
  • ゲーム中のパラメータや状態の保持

特に知っておきたいのは、Unityのシリアライザーはフィールド(変数)に直接作用するという点です。つまり、プロパティではなく「変数」が対象になるんですね。

シリアライズされる条件

フィールドがシリアライズ対象になるためには、以下の条件を満たしている必要があります。

  • public で宣言されている、または [SerializeField] が付いている
  • static ではない
  • constreadonly ではない

また、シリアライズ可能な型にはルールがあります。

  • プリミティブ型(int, float, bool, stringなど)
  • Unity組み込み型(Vector3, Color など)
  • [Serializable] が付いたクラスや構造体
  • UnityEngine.Object を継承したオブジェクト(GameObjectやMaterialなど)
  • 上記の配列や List<T>

もっと簡単にセーブ・ロードしたい人へ

ここまで説明したように、Unity標準のシリアライズでも多くのことができます。でも、実際に「セーブデータを作りたい」「暗号化したい」「複雑なデータを保存したい」となると少し大変…。そんなときに役立つのがこちらのアセットです👇

Easy Save 3 – ゲームデータ保存を圧倒的にラクにする定番アセット

セーブ&ロード機能を数行で実装できるので、特に初心者の方や「早くゲーム本編に集中したい!」という方におすすめです。


[SerializeField] と [Serializable] の違いと使い分け

Unityでシリアライズを使うときに、よく目にするのが [SerializeField][Serializable] です。名前が似ていてややこしいですが、それぞれ役割が違うのでしっかり整理しておきましょう。

[SerializeField] 属性

[SerializeField] は、「privateな変数をInspectorに表示したい」ときに使います。通常、publicにすればInspectorに表示されますが、他のクラスから自由にアクセスできてしまい、カプセル化が崩れてしまいます。

そこで private を維持したまま [SerializeField] を付けると、Inspectorには表示されるけれど外部からはアクセスできないという、いいとこ取りの状態を作れるんです✨


[SerializeField] 
private int hp = 100;

これでInspector上ではHPを調整でき、コード上では他クラスから直接変更されるのを防げます。

[Serializable] 属性

一方、[Serializable] は「クラスや構造体をシリアライズ可能にする」ための属性です。これを使うと、カスタムクラスのプロパティがInspectorに展開され、個別に編集できるようになります。


[System.Serializable]
public class Status {
    [SerializeField] private int hp;
    [SerializeField] private int mp;
    [SerializeField] private int attackPower;
}

このように定義したクラスを、他のMonoBehaviourクラスにフィールドとして持たせれば、Inspector上で「Status」という項目が展開され、中身の数値を自由に編集できるようになります。

Inspectorをもっと便利にするには?

Unity標準のInspectorはシンプルで使いやすいですが、「もっと見やすくしたい」「条件によって表示を切り替えたい」と感じることもあると思います。そんなときに便利なのがこちら👇

Odin Inspector & Serializer – Inspectorを超強化できるアセット

これを導入すれば、複雑なクラスでも直感的に編集できたり、開発効率が一気に上がります。特に [Serializable] を活用したカスタムクラスを多用する人には必須級のアセットです。


高度なシリアライズ:SerializeReferenceとISerializationCallbackReceiver

ここからはちょっと応用編。Unityのシリアライザーは便利ですが、標準のままでは扱えないケースもあります。そんなときに役立つのが [SerializeReference]ISerializationCallbackReceiver です。

SerializeReference属性

通常のシリアライズでは、カスタムクラスを「値としてコピー」する形で扱います。そのため、複数の変数が同じオブジェクトを参照していても、それぞれ別々のコピーとして保存されてしまいます。

そこで [SerializeReference] を使うと、Unityは「参照」としてオブジェクトを保存するようになります。これにより…

  • 複数のフィールドで同じインスタンスを共有できる
  • 参照がnullのままでも保持できる
  • ポリモーフィズム(継承クラスのシリアライズ)に対応できる

つまり「オブジェクトの関係性」をそのまま保存できるようになるわけです。 特にAIやキャラクターの設定など、柔軟なデータ構造が必要な場面で役立ちます。

ISerializationCallbackReceiverの活用

Unity標準では Dictionary や多次元配列など、いくつかのデータ型はシリアライズできません。そこで使うのが ISerializationCallbackReceiver インターフェースです。

この仕組みを使えば、シリアライズ直前にデータをUnityが扱える形(配列やリストなど)に変換し、復元時に元の形に戻すことができます。


[System.Serializable]
public class ExampleDictionary : ISerializationCallbackReceiver {
    [SerializeField] private List&lt;string&gt; keys = new List&lt;string&gt;();
    [SerializeField] private List&lt;int&gt; values = new List&lt;int&gt;();
    private Dictionary&lt;string, int&gt; dict = new Dictionary&lt;string, int&gt;();

    public void OnBeforeSerialize() {
        keys.Clear();
        values.Clear();
        foreach (var kvp in dict) {
            keys.Add(kvp.Key);
            values.Add(kvp.Value);
        }
    }

    public void OnAfterDeserialize() {
        dict = new Dictionary&lt;string, int&gt;();
        for (int i = 0; i &lt; keys.Count; i++) {
            dict[keys[i]] = values[i];
        }
    }
}

これでInspectorに直接は表示されないけれど、Dictionaryとして使えるシリアライズ処理が実現できます。

AIシステムでも役立つ!

シリアライズを深く理解すると、キャラクターAIや状態管理にも応用できます。たとえば、ビヘイビアツリーを使ったAIでは、複雑なデータ構造を保存・読み込みする必要があるため、シリアライズの知識が大活躍します。

Behavior Designer Pro – DOTS対応の強力なビヘイビアツリーアセット

これを使えば、シリアライズで学んだ考え方をそのまま活かしつつ、キャラクターの行動パターンや敵AIを視覚的に組み立てられます。特にRPGやアクションゲームで「賢い動きをする敵」を作りたい人におすすめです。


シリアライズとUnityシステムの関係

シリアライズは「ただデータを保存する仕組み」ではなく、Unityのいろいろな機能の土台になっています。普段の開発で何気なく使っているものも、実はシリアライズに支えられているんです。

シリアライズが使われている代表例

  • Prefab: ゲームオブジェクトを保存して再利用できるのは、内部的にシリアライズされているからです。
  • Inspector: フィールドを編集したとき、その値はシリアライズされて保存されます。
  • ホットリロード: スクリプトを編集してもInspectorの値が保持されるのは、シリアライズのおかげ。
  • Instantiate: オブジェクト生成は、シリアライズされたデータをコピーして復元しています。

ゲーム演出や制作フローにも直結

たとえば「エフェクトの設定」や「キャラクターデータの管理」なども、シリアライズを理解するとグッと楽になります。Inspectorで細かい数値をいじって、そのまま保存できるのはシリアライズの恩恵なんです。

もっと深く演出やキャラクター制作に踏み込みたい方には、以下の書籍もおすすめです👇

シリアライズの知識をベースに、こうした本で演出やキャラクター作りを学ぶと、開発の幅が大きく広がりますよ✨


まとめ

今回は、Unityにおけるシリアライズについて、基礎から応用までを解説しました。 シリアライズはデータを保存・復元する仕組みであり、InspectorやPrefab、シーン保存など、Unityのあらゆる部分で使われています。

今回のポイント

  • [SerializeField] は「privateをInspectorに表示したいとき」に便利
  • [Serializable] は「カスタムクラスをInspectorに展開」できる
  • [SerializeReference] を使うと参照やポリモーフィズムも扱える
  • ISerializationCallbackReceiver でDictionaryなど非対応データも保存可能に
  • UnityのPrefab、Inspector、ホットリロードもシリアライズが基盤

また、標準機能だけでなく、アセットを組み合わせることで開発が一気に楽になります。

シリアライズを正しく理解すれば、データの扱いがもっと自由に、もっと安全にできるようになります。ぜひ今回の内容を参考にして、あなたのUnity開発に役立ててくださいね✨


よくある質問(FAQ)

Q
public変数と[SerializeField]はどちらを使うべき?
A

基本的には [SerializeField] を付けた private フィールドがおすすめです。 こうすることで、Inspectorから調整できる一方、他のクラスからの直接アクセスを防げるので安全性が高まります。 「外部からアクセスさせたいがInspectorには出したくない」ときは public[HideInInspector] を組み合わせる方法もあります。

Q
Dictionaryを保存できないのはなぜ?
A

Unity標準のシリアライザーは Dictionary に対応していないためです。 この場合は ISerializationCallbackReceiver を実装して「配列に変換して保存→復元時にDictionaryに戻す」という手順を踏めば解決できます。 あるいは Easy Save 3 のような外部アセットを利用すると、手間なく扱えるのでおすすめです。

Q
ScriptableObjectとSerializableの違いは?
A

[Serializable] は「クラスや構造体をInspectorで展開可能にする」ための属性で、主にコンポーネント内の補助データ管理に使われます。 一方で ScriptableObject は「アセットファイルとして独立管理できるデータの入れ物」で、複数シーンや複数オブジェクトで共有するときに便利です。 つまり、「コンポーネント内で完結するデータ」なら [Serializable]、「独立したデータアセット」として管理したいなら ScriptableObject を選びましょう。

※当サイトはアフィリエイト広告を利用しています。リンクを経由して商品を購入された場合、当サイトに報酬が発生することがあります。

※本記事に記載しているAmazon商品情報(価格、在庫状況、割引、配送条件など)は、執筆時点のAmazon.co.jp上の情報に基づいています。
最新の価格・在庫・配送条件などの詳細は、Amazonの商品ページをご確認ください。

スポンサーリンク