UnityUnityメモ

Unityのデータ管理を最適化!SerializableとScriptableObjectの違いと活用法

Unity

1. はじめに

ゲーム開発では、プレイヤーのステータスやアイテムデータ、敵の能力値など、さまざまなデータを管理する必要があります。しかし、「どの方法でデータを管理すればいいのか?」と悩むことはありませんか?

Unityには、データを効果的に管理するための仕組みとして Serializable(シリアライズ可能なクラス)ScriptableObject(スクリプタブルオブジェクト) があります。これらを使いこなすことで、ゲームのデータ管理をよりスマートにし、開発の効率を大幅に向上させることができます。

この記事では、SerializableとScriptableObjectの違いを詳しく解説し、それぞれの活用方法を具体的なコード例とともに紹介します。これを読めば、「どの場面でSerializableを使うべきか?」「ScriptableObjectをどう活用すると便利なのか?」がバッチリ理解できます!

さあ、Unityのデータ管理の最適解を見つけましょう!




2. Serializableとは?

Serializable(シリアライズ可能なクラス)とは、クラスや構造体のデータを保存や転送しやすい形に変換できる仕組みです。Unityでは、[System.Serializable] という属性を使ってクラスをシリアライズ可能にすることで、Inspector(インスペクター)上でデータを編集できるようになります。

通常、C#のクラスはそのままではUnityのインスペクターに表示されません。しかし、Serializableを適用すると、スクリプトをアタッチしたオブジェクトのInspector上で値を設定できるようになります。


Serializableの基本的な使い方

以下のように、クラスの定義の前に [System.Serializable] を付けることで、そのクラスをシリアライズ可能にできます。

using UnityEngine;

[System.Serializable]
public class PlayerStats
{
public string playerName;
public int health;
public int attackPower;
}

このクラスを、たとえば MonoBehaviour を継承したスクリプト内でリストとして管理すると、Inspectorで編集可能になります。

using UnityEngine;
using System.Collections.Generic;

public class GameManager : MonoBehaviour
{
public List<PlayerStats> playerStatsList;
}

このスクリプトをGameObjectにアタッチすると、以下のようにInspectorでデータを設定できるようになります。


Serializableのメリット

Inspector上で編集可能になる
Inspectorで簡単にデータを変更できるため、開発時にコードを書き換えずに値を調整できます。

クラスを使ってデータを整理できる
変数を一つずつ定義するのではなく、まとまったデータ構造を作成できるので、コードの可読性が向上します。

スクリプトのデータ管理がシンプルになる
複数のオブジェクトに同じデータ構造を適用しやすく、データの追加・変更が容易になります。


Serializableのデメリット

⚠️ データの共有には向かない
Serializableクラスはオブジェクトごとにデータが保存されるため、シーンをまたいでデータを保持したり、複数のオブジェクトで同じデータを参照したい場合には適していません

⚠️ スクリプトの肥大化の原因になることも
シリアライズしたクラスのデータが増えすぎると、スクリプトが長くなり管理しづらくなることがあります。


Serializableの具体的な活用例

プレイヤーのステータス管理
敵キャラクターのパラメータ設定
アイテムデータの管理(武器、ポーションなど)

Serializableは、オブジェクトごとに異なるデータを設定したいときに特に便利です。次のセクションでは、ScriptableObjectを使ったデータ管理について詳しく解説します!




3. ScriptableObjectとは?

ScriptableObject(スクリプタブルオブジェクト) は、Unityのデータ管理をより効率的にする特別なクラスです。
通常、ゲームデータを管理する際は MonoBehaviour を継承したスクリプトを使いますが、ScriptableObjectを使うと、シーンとは独立したデータを保存・共有できるようになります。

例えば、ゲーム内のキャラクターのステータスやアイテムデータを1つのアセットとして作成し、それを複数のシーンやスクリプトで使い回すことができます。


ScriptableObjectの基本的な書き方

ScriptableObjectを作成するには、ScriptableObject を継承したクラスを作り、CreateAssetMenu 属性を付けます。

using UnityEngine;

[CreateAssetMenu(fileName = "NewPlayerStats", menuName = "Game Data/Player Stats")]
public class PlayerStats : ScriptableObject
{
public string playerName;
public int health;
public int attackPower;
}

このスクリプトを作成したら、Unityエディタでアセットとして生成できます。

  1. プロジェクトウィンドウで右クリック
  2. 「Create」→「Game Data」→「Player Stats」を選択
  3. 新しいScriptableObjectアセットが作成される

このアセットにデータを入力すると、他のスクリプトから参照できるようになります。


ScriptableObjectを使うメリット

シーンに依存しないデータの管理ができる
ゲームの設定データや、アイテム・敵のステータスなどを独立したアセットとして保存できるため、シーン間でデータを簡単に共有できます。

メモリ管理が最適化される
MonoBehaviour を使ったスクリプトとは異なり、不要なインスタンスを作成しないため、メモリ消費を抑えることができます。

スクリプトの整理がしやすい
ゲームデータを個別のScriptableObjectに分けることで、スクリプトの肥大化を防ぎ、データ管理がシンプルになります。

複数のオブジェクトで同じデータを参照できる
例えば、敵のステータスデータを一つのScriptableObjectで管理すれば、全ての敵キャラクターが同じデータを参照できるようになり、変更も簡単になります。


ScriptableObjectのデメリット

⚠️ データの保存に制限がある
ScriptableObjectのデータは ゲーム実行中に変更しても、元のアセットには保存されません
(データの永続化が必要な場合は PlayerPrefsJSON保存 などの別の仕組みが必要)

⚠️ リアルタイムでの動的変更には向かない
ScriptableObjectはアセットとして静的に管理されるため、ゲーム中にデータを頻繁に変更したい場合には、別の仕組みを考える必要があります。


ScriptableObjectの具体的な活用例

アイテムデータの管理(武器、ポーションなど)
敵キャラクターのステータス設定
ゲームの設定データ(サウンド音量、難易度など)
エフェクトやパーティクルの設定データ

ScriptableObjectは、**「シーンに依存しないデータを管理するのに最適な仕組み」**です。
次のセクションでは、SerializableとScriptableObjectの具体的な使い方について詳しく解説していきます!




4. 具体的な活用方法

SerializableとScriptableObjectの理解を深めたところで、実際にどのように活用できるのか、具体的な例を交えて解説します。ここでは、以下の3つのケースを紹介します。

  1. Serializableを使ったデータ管理
  2. ScriptableObjectを使ったデータ管理
  3. ScriptableObjectを使ったデータ共有

① Serializableを使ったデータ管理

プレイヤーステータスを管理する場合

Serializableを活用すると、Inspector上でデータを編集できるようになり、開発がスムーズになります。例えば、プレイヤーのステータスを管理するには以下のようなコードを使います。

📌 コード例:Serializableでプレイヤーステータスを管理

using UnityEngine;
using System.Collections.Generic;

[System.Serializable]
public class PlayerStats
{
public string playerName;
public int health;
public int attackPower;
}

public class GameManager : MonoBehaviour
{
public List<PlayerStats> playerStatsList;
}

💡ポイント

PlayerStats クラスを [System.Serializable] にすることで、Inspectorでデータを編集できる
GameManagerList<PlayerStats> を作成することで、複数のプレイヤーのデータを管理できる

このスクリプトをGameObjectにアタッチすると、Inspectorでデータを直接入力できるようになります。


② ScriptableObjectを使ったデータ管理

敵キャラクターのステータスを管理する場合

Serializableはオブジェクトごとにデータを持つのに対し、ScriptableObjectを使うと、データをアセットとして保存し、複数のスクリプトから参照できるようになります。

📌 コード例:ScriptableObjectで敵キャラクターのデータを管理

using UnityEngine;

[CreateAssetMenu(fileName = "NewEnemyStats", menuName = "Game Data/Enemy Stats")]
public class EnemyStats : ScriptableObject
{
public string enemyName;
public int health;
public int attackPower;
}

このスクリプトを作成したら、Unityエディタでアセットとして作成できます。

  1. プロジェクトウィンドウで右クリック
  2. 「Create」→「Game Data」→「Enemy Stats」を選択
  3. 新しいScriptableObjectアセットが作成される

次に、このScriptableObjectをゲーム内で使うためのスクリプトを作成します。

using UnityEngine;

public class Enemy : MonoBehaviour
{
public EnemyStats enemyStats;

void Start()
{
Debug.Log(enemyStats.enemyName + " のHPは " + enemyStats.health);
}
}

💡ポイント

EnemyStats はScriptableObjectとしてアセットに保存されるため、複数の敵が同じデータを参照可能
Enemy クラスで EnemyStats を使い、Inspectorからデータを設定できる
✅ ステータスの変更が一箇所(ScriptableObject)で完結し、メンテナンスが簡単


ScriptableObjectは便利ですが、プロジェクトが大きくなると管理が大変になります。そんなときに役立つのが「ScriptableObject Manager」です!このアセットを使えば、プロジェクト内のScriptableObjectを一覧で管理でき、効率的に編集できます。ScriptableObject Manager をチェックする

③ ScriptableObjectを使ったデータ共有

シーン間でプレイヤーデータを共有する場合

通常、MonoBehaviour でデータを管理すると、シーンをまたいだ際にデータがリセットされてしまいます。ですが、ScriptableObjectを使えば、シーンを超えてデータを共有することができます。

📌 コード例:ScriptableObjectを使ったデータ共有

using UnityEngine;

[CreateAssetMenu(fileName = "NewGameSettings", menuName = "Game Data/Game Settings")]
public class GameSettings : ScriptableObject
{
public int volume;
public int difficulty;
}

このスクリプトを使って、ゲームの設定データを保存するScriptableObjectを作成します。
次に、このデータをゲーム内で活用するスクリプトを作ります。

using UnityEngine;

public class SettingsManager : MonoBehaviour
{
public GameSettings gameSettings;

void Start()
{
Debug.Log("現在の音量: " + gameSettings.volume);
Debug.Log("難易度: " + gameSettings.difficulty);
}
}

この GameSettings アセットを、全てのシーンで共有すれば、設定データを統一して管理できるようになります。

💡ポイント

ScriptableObject を使うことでデータをアセット化し、シーンをまたいで利用できる
✅ ゲームの難易度やサウンド設定など、変更を一箇所で管理できる
MonoBehaviour を使わないため、不要なオブジェクトの生成を防ぎ、メモリ使用量を削減できる


Serializableを使うとインスペクターでデータを管理できますが、デフォルトの辞書型(Dictionary)はインスペクターで編集できません。でも、「Serialized Dictionary」を使えば、簡単にインスペクターで辞書を編集できます!Serialized Dictionary をチェックする

まとめ

使用方法便利なポイント具体例
Serializableインスペクターで管理できるプレイヤーのステータス管理
ScriptableObjectシーンを超えてデータを共有アイテムデータ、敵のステータス
ScriptableObject(データ共有)設定データを統一ゲームの音量・難易度設定

SerializableとScriptableObjectを状況に応じて使い分けることで、データ管理がよりシンプルに、効率的になります。




5. SerializableとScriptableObjectの使い分け

SerializableとScriptableObjectは、どちらもデータ管理を効率化するための仕組みですが、用途によって使い分ける必要があります。ここでは、それぞれの特性を比較しながら、最適な活用方法を解説します。


📌 どんなときにSerializableを使うべきか?

✅ 1. インスペクターで管理したいデータ

Serializableを使うと、データをInspector(インスペクター)で直接編集できるようになります。これは、プレイヤーのステータスや装備アイテムなど、オブジェクトごとに異なるデータを持たせたい場合に便利です。

📝 例:プレイヤーステータスを管理

[System.Serializable]
public class PlayerStats
{
public string playerName;
public int health;
public int attackPower;
}

public class GameManager : MonoBehaviour
{
public PlayerStats playerStats;
}

🔹 メリット:

  • オブジェクトごとに異なるデータを持たせることができる
  • 直感的にデータを変更できる(Inspectorから編集可能)
  • 複数のオブジェクトをリスト管理しやすい

🔸 デメリット:

  • データの共有が難しい(シーンをまたぐとリセットされる)
  • スクリプトが肥大化しやすい

📌 どんなときにScriptableObjectを使うべきか?

✅ 1. シーンを超えてデータを共有したい

ScriptableObjectは、ゲームデータをシーン間で共有したいときに最適です。たとえば、敵のステータスやアイテムデータなど、ゲーム全体で共通して使うデータは、ScriptableObjectとして保存することで、シーンを変更してもデータが維持されます。

📝 例:敵のステータスを管理

[CreateAssetMenu(fileName = "NewEnemyStats", menuName = "Game Data/Enemy Stats")]
public class EnemyStats : ScriptableObject
{
public string enemyName;
public int health;
public int attackPower;
}

👆このスクリプトで作成したScriptableObjectをシーン間で使いまわせる!

🔹 メリット:

  • シーンを超えてデータを共有できる
  • データの更新が1カ所で完結する(管理が楽)
  • スクリプトの負担を軽減し、メモリ管理が最適化される

🔸 デメリット:

  • ゲーム実行中に変更したデータは保存されない(別の方法で保存が必要)
  • リアルタイムで頻繁に変更するデータには向かない



📌 SerializableとScriptableObjectの比較表

項目SerializableScriptableObject
インスペクターで編集可能✅ できる✅ できる
シーンを超えたデータの共有❌ できない✅ できる
メモリ管理の最適化❌ 非効率✅ 効率的
データの保存✅ オブジェクトに紐づく❌ 実行中の変更は保存されない
管理しやすさ⚠️ データが増えると肥大化✅ 1カ所で管理できる

「結局どっちを使うべき?」と悩んだら、Odin Inspectorのようなアセットを使うのもアリ! Odin Inspectorなら、SerializableクラスやScriptableObjectをより直感的に編集でき、開発の手間を大幅に削減できます。Odin Inspector をチェックする


📌 組み合わせて使う方法

SerializableとScriptableObjectは、それぞれの長所を活かして組み合わせて使うことが可能です。

✅ 1. Serializableを使ってデータ構造を定義し、ScriptableObjectでデータを管理

たとえば、敵のステータス情報をSerializableクラスで作り、それをScriptableObjectに格納することで、柔軟なデータ管理が可能になります。

[System.Serializable]
public class EnemyData
{
public string enemyName;
public int health;
public int attackPower;
}

[CreateAssetMenu(fileName = "NewEnemyDataList", menuName = "Game Data/Enemy List")]
public class EnemyDataList : ScriptableObject
{
public List<EnemyData> enemyList;
}

このようにすると、Inspectorで敵のリストを編集しながら、シーン間でデータを共有することができます。


📌 まとめ:どう使い分けるべき?

✅ Serializableが向いているケース

  • 個々のオブジェクトごとに異なるデータを持たせたい
  • データをInspectorで直感的に編集したい
  • 一時的なデータを保持したい(シーンごとのデータ管理)

✅ ScriptableObjectが向いているケース

  • シーンを超えてデータを共有したい
  • ゲームの設定データ、敵やアイテムのデータなど、共通データを管理したい
  • メモリ管理を最適化したい

✅ 両方を組み合わせると便利なケース

  • Serializableでデータ構造を定義し、ScriptableObjectでデータを統括管理する

これらを適切に使い分けることで、ゲームのデータ管理がより効率的になり、開発がスムーズになります!




6. まとめ

Unityでゲームを開発する上で、データ管理の最適化はとても重要です。
この記事では、SerializableとScriptableObjectの違いと使い方を詳しく解説しました。
ここで、もう一度それぞれの特徴を振り返りましょう。


📌 SerializableとScriptableObjectの特徴まとめ

項目SerializableScriptableObject
用途インスペクターでデータを管理シーンを超えたデータの共有
シーンをまたぐデータの保持❌ できない✅ できる
Inspectorでの編集✅ 可能✅ 可能
メモリ管理❌ 効率が悪くなることがある✅ 不要なインスタンスを作らないので軽量
データの保存✅ プレハブやオブジェクトごと❌ 実行中の変更は保存されない
リアルタイムのデータ変更✅ 可能⚠️ 実行中の変更は保存されない

📌 どのように使い分ければいいのか?

💡 Serializableを使うべきケース

  • プレイヤーのステータス、敵のパラメータなど、オブジェクトごとに異なるデータを管理
  • リストや配列でデータを整理し、Inspectorで簡単に編集したい
  • シーンごとに異なるデータを管理する場合

💡 ScriptableObjectを使うべきケース

  • シーン間でデータを共有したい(ゲーム設定、アイテムデータ、敵リストなど)
  • データをアセットとして保存し、複数のオブジェクトが共通して参照できるようにしたい
  • メモリ管理を最適化したい(大量のデータをスクリプト上に持たせたくない)

💡 両方を組み合わせると便利なケース

  • Serializableでデータ構造を定義し、ScriptableObjectでゲーム全体のデータを統括管理する

📌 ゲーム開発に活かすポイント

  • プレイヤーのステータスや敵のパラメータはSerializableで定義し、各オブジェクトごとに管理
  • ゲーム全体の設定データ(難易度、サウンド設定)はScriptableObjectで一元管理
  • 武器やアイテムのデータもScriptableObjectにすると、データ管理がしやすくなる

📌 この記事のポイント

SerializableはInspectorでデータを管理するために便利!
ScriptableObjectはシーンを超えてデータを共有するのに最適!
どちらも組み合わせることで、より効率的なデータ管理が可能!


SerializableとScriptableObjectを適材適所で使うことが、データ管理の最適解! とはいえ、プロジェクトが大きくなると、もっと便利なツールが欲しくなりますよね? そんなときは、Asset Storeの「ScriptableObject Manager」「Serialized Dictionary」「Odin Inspector」を活用して、データ管理をよりスマートに!

この知識を活かせば、Unityでのゲーム開発がスムーズになり、データ管理がシンプルで直感的になります。ぜひ、SerializableとScriptableObjectを適材適所で活用し、快適なゲーム開発を楽しんでください!




よくある質問(FAQ)

Q
ScriptableObjectはどのように保存される?
A

Unityエディタ上ではアセットとして保存され、プレハブのように使える。ゲーム実行時に変更しても、元のデータは変わらない。

Q
Serializableクラスはどのタイミングで使うべき?
A

一時的なデータの管理や、インスペクター上でオブジェクトの情報を見やすくするために使う。

Q
ScriptableObjectを使うとパフォーマンスが良くなる?
A

大量のデータを使いまわす場合はメモリ使用量を抑えられるため、パフォーマンスが向上することがある。

タイトルとURLをコピーしました