• ゲーム
  • Industry
  • リソース
  • コミュニティ
  • 学習
  • サポート
開発
Unityエンジン
任意のプラットフォーム向けに2Dおよび3Dゲームを構築
ダウンロードプランと価格
収益化
アプリ内課金(IAP)
ストア全体でIAPを発見し、管理する
Mediation
収益を最大化し、マネタイズを最適化する
Ad Quality
アプリのユーザーエクスペリエンスを保護する
Tapjoy
長期的なユーザーの忠誠心を構築する
すべてのマネタイズ製品
詳しく見る
詳しく見る
発見され、モバイルユーザーを獲得する
UnityベクターAI
プレイヤーを適切なゲームに接続する
Auraのオンデバイス広告
ピークエンゲージメント時にデバイス上のユーザーにリーチする
すべての成長製品
活用事例
3Dコラボレーション
リアルタイムで3Dプロジェクトを構築およびレビューする
没入型トレーニング
没入型環境でのトレーニング
顧客体験
インタラクティブな3D体験を作成する
すべての業界ソリューション
業界
製造業
運用の卓越性を達成する
小売
店内体験をオンライン体験に変換する
自動車
革新と車内体験を高める
全業界
技術ライブラリ
ドキュメント
公式ユーザーマニュアルとAPIリファレンス
開発者ツール
リリースバージョンと問題追跡
ロードマップ
今後の機能をレビューする
用語集
技術用語のライブラリ
インサイト
ケーススタディ
実際の成功事例
ベストプラクティスガイド
専門家のヒントとコツ
すべてのリソース
新機能
ブログ
更新情報、情報、技術的ヒント
お知らせ
ニュース、ストーリー、プレスセンター
コミュニティハブ
ディスカッション
議論、問題解決、つながる
イベント
グローバルおよびローカルイベント
コミュニティストーリー
Made with Unity
Unityクリエイターの紹介
ライブストリーム
開発者、クリエイター、インサイダーに参加する
Unity Awards
世界中のUnityクリエイターを祝う
すべてのレベルに対応
Unity Learn
無料でUnityスキルをマスターする
プロフェッショナルトレーニング
Unityトレーナーでチームをレベルアップ
Unity初心者向け
スタートガイド
学習を開始しましょう
Unityエッセンシャルパスウェイ
Unity は初めてですか?旅を始めましょう
ハウツーガイド
実用的なヒントとベストプラクティス
教育
学生向け
キャリアをスタートさせる
教育者向け
教育を大幅に強化
教育機関向けライセンス
Unityの力をあなたの機関に持ち込む
認定教材
Unityのマスタリーを証明する
サポートオプション
ヘルプを得る
Unityで成功するためのサポート
Success Plan
専門的なサポートで目標を早く達成する
FAQ
よくある質問への回答
お問い合わせ
私たちのチームに連絡する
プランと価格
言語設定
  • English
  • Deutsch
  • 日本語
  • Français
  • Português
  • 中文
  • Español
  • Русский
  • 한국어
ソーシャル
通貨
購入
  • プロダクト
  • Unity Ads
  • サブスクリプション
  • Unity Asset Store
  • リセラー
教育
  • 学生
  • 教育関係者
  • 教育機関
  • 認定資格試験
  • 学ぶ
  • スキル開発プログラム
ダウンロード
  • Unity Hub
  • ダウンロードアーカイブ
  • ベータプログラム
Unity Labs
  • ラボ
  • 研究論文
リソース
  • Learn プラットフォーム
  • コミュニティ
  • ドキュメント
  • Unity QA
  • FAQ
  • サービスのステータス
  • ケーススタディ
  • Made with Unity
Unity
  • 当社について
  • ニュースレター
  • ブログ
  • イベント
  • キャリア
  • ヘルプ
  • プレス
  • パートナー
  • 投資家
  • アフィリエイト
  • セキュリティ
  • ソーシャルインパクト
  • インクルージョンとダイバーシティ
  • お問い合わせ
Copyright © 2025 Unity Technologies
  • 法規事項
  • プライバシーポリシー
  • クッキーについて
  • 私の個人情報を販売または共有しないでください

「Unity」の名称、Unity のロゴ、およびその他の Unity の商標は、米国およびその他の国における Unity Technologies またはその関係会社の商標または登録商標です(詳しくはこちら)。その他の名称またはブランドは該当する所有者の商標です。

Hero background image

ScriptableObject でゲームデータとロジックを分離

このウェブページは、お客様の便宜のために機械翻訳されたものです。翻訳されたコンテンツの正確性や信頼性は保証いたしかねます。翻訳されたコンテンツの正確性について疑問をお持ちの場合は、ウェブページの公式な英語版をご覧ください。
ここをクリックしてください。

このページでは、ゲームコード内のロジックからデータを分離するデータコンテナとして ScriptableObject を使用する方法について説明します。

これは、eBook「Create modular game architecture in Unity with ScriptableObjects」に付属するデモで、Unity開発者を支援するために作成された6つのミニガイドシリーズの第2弾です。

このデモは、古典的なボールとパドルを使ったアーケードゲームのメカニクスに着想を得たもので、ScriptableObject がテスト可能でスケーラブル、かつデザイナーにとって使いやすいコンポーネントの作成にどのように役立つかを示しています。

この e ブック、デモプロジェクト、およびこれらのミニガイドは、Unity プロジェクトで ScriptableObject クラスを使用してプログラミングデザインパターンを使用するためのベストプラクティスを提供します。これらのヒントは、コードを簡素化し、メモリ使用量を削減し、コードの再利用性を促進するのに役立ちます。

このシリーズには、次の記事が含まれています。

  • Unity ScriptableObjectsデモの使用を開始する
  • Unity プロジェクトで ScriptableObject ベースの列挙型を使用する
  • ScriptableObject をデリゲートオブジェクトとして使用する
  • ゲームコードで ScriptableObject をイベントチャンネルとして使用する
  • ScriptableObject ベースのランタイムセットの使用方法
  • 始める前の重要事項
  • データコンテナ
  • 一般的なワークフロー
  • ScriptableObject と MonoBehaviour の比較
  • Patterns デモ
  • フライウェイトパターンによるゲームデータの保存
  • PaddleBallSO ゲームデータ
  • デュアルシリアライズの例:レベルレイアウト
  • ScriptableObject データコンテナのその他の用途
  • その他の ScriptableObject リソース

始める前の重要事項

ScriptableObject デモプロジェクトとこのミニガイドシリーズを掘り下げる前に、その中核をなすデザインパターンは単なるアイデアに過ぎないことを覚えておいてください。すべての状況に当てはまるわけではありません。これらのテクニックは、Unity と ScriptableObject の新しい使い方を学ぶのに役立ちます。

それぞれのパターンには長所と短所があります。特定のプロジェクトにとって意味のあるものだけを選びましょう。デザイナーは Unity エディターに大きく依存していますか?ScriptableObject ベースのパターンは、開発者と共同作業するのに良い選択肢です。

最終的には、プロジェクトやチームに合ったコードアーキテクチャがベストです。

tab2

データコンテナ

ソフトウェア開発者は、多くの場合、アプリケーションを小さな自己完結型のユニットに分割するモジュール性に懸念を持っています。各モジュールは、アプリケーションの機能の特定の側面を担います。

Unity では、ScriptableObject はロジックからデータを分離するのに役立ちます。

ScriptableObject は、特に静的なデータを格納するのに適しています。これにより、ゲームの統計、アイテムや NPC の設定値、キャラクターの会話などに最適です。

ゲームプレイデータをビヘイビアロジックから分離することで、プロジェクトの独立した各パーツのテストとメンテナンスが容易になります。この「懸念の分離」により、必要な変更を加える際に、意図しない副作用や望ましくない副作用を減らすことができます。

Download PaddleBallSO
tab3

一般的なワークフロー

ScriptableObject ワークフローの復習をご希望の場合は、こちらの Unity Learn 記事が役立ちます。そうでない場合は、以下の簡単な説明をご覧ください。

ScriptableObject を定義します。作成するには、格納するデータのフィールドとプロパティを持つ ScriptableObject 基本クラスを継承する C# クラスを定義します。ScriptableObject は、MonoBehaviour で利用可能な同じデータ型を格納できるため、汎用性の高いデータコンテナとなります。 エディターから CreateAssetMenuAttribute を追加して、プロジェクトでのアセットの作成を容易にします。

アセットの作成:ScriptableObject クラスを定義したら、その ScriptableObject のインスタンスをプロジェクト内に作成できます。これはディスクに保存されたアセットとして表示され、異なるゲームオブジェクトやシーンで再利用できます。

設定値:アセットを作成したら、Inspector でフィールドとプロパティの値を設定することで、アセットにデータを入力します。

アセットの使用:アセットがデータを保持したら、変数またはフィールドからデータを参照します。ScriptableObject アセットに加えられた変更は、プロジェクト全体に反映されます。

ScriptableObject は、ゲームのさまざまな部分でデータコンテナとして再利用できます。例えば、ScriptableObject 内で武器やキャラクターのプロパティを定義し、プロジェクト内のどこからでもそのアセットを参照できます。

注:また、実行時に CreateInstance メソッドを使用して ScriptableObject を生成することもできます。ただし、データストレージについては、通常は CreateAssetMenuAttribute を使用して事前に ScriptableObject アセットを作成します。

tab4

ScriptableObject と MonoBehaviour の比較

ScriptableObject が MonoBehaviour よりもデータストレージに適している理由をよりよく理解するために、それぞれの空のバージョンを比較します。「Asset Serialization」を「Mode」に設定します。「Project Settings」で「Force Text」を選択すると、YAML マークアップがテキストとして表示されます。

それ以外の場合は空の MonoBehaviour で新しいゲームオブジェクトを作成します。次に、空の ScriptableObject アセットと比較します。これらを横に並べると、上の画像のような見た目になります。

ScriptableObject は MonoBehaviour と比較して軽量で、Transform コンポーネントのような MonoBehaviour に伴うオーバーヘッドを持ちません。これにより、ScriptableObject のメモリフットプリントが小さくなり、データストレージ用に最適化されます。

tab5

Patterns デモ

ScriptableObject はアセットとして保存されるため、再生モード以外でも保持されるので便利です。例えば、ScriptableObject のデータは、新しいシーンをロードした場合でもどこからでも利用できます。

Patterns デモの例には、自分でテストできる基本的なクレジット画面があります。Credits_Data ScriptableObject を変更し、Update を押して、保存されているテキストを確認します。

大量のダイアログを含む RPG や、あらかじめ用意されたスクリプトを含むチュートリアルシーンがある場合、これは大量のデータを保存する一般的な方法です。

ScriptableObject 内のデータは変更されると即座に更新されますが、私たちのプロジェクトでは、手動で画面を更新するには Update ボタンが必要です。UI Toolkit ベースの画面は 1 回のみビルドされ、データが変更されたときに通知を受ける必要があります。

更新を自動的に同期したい場合は、ScriptableObject 内にイベントを作成します。たとえば、この ExampleSO スクリプトは、ExampleValue が変更されるたびに OnValueChanged イベントを呼び出します。以下のコード例をご覧ください。

次に、リッスンしている UI オブジェクトに OnValueChanged をサブスクライブさせ、適宜更新します。

Download PaddleBallSO
tab6

フライウェイトパターンによるゲームデータの保存

ScriptableObject は、多くのオブジェクトが同じデータを共有するときに輝きます。例えば、同じ攻撃速度と最大ライフを持つユニットが多数あるストラテジーゲームを制作している場合、それらの値をすべてのゲームオブジェクトに個別に保存するのは非効率的です。

代わりに、共有データを 1 か所に統合し、各オブジェクトがその共有場所を参照するようにできます。ソフトウェア設計では、これはフライウェイトパターンと呼ばれる最適化です。このようにコードを再構築することで、大量の値をコピーすることがなくなり、メモリフットプリントを削減できます。

PaddleBallSO では、GameDataSO ScriptableObject は共有データストレージとして機能します。

Paddle スクリプトと Ball スクリプトは、一般的な設定(速度、質量、物理演算の跳ね返りなど)のコピーを別に保持するのではなく、可能な限り同じ GameDataSO インスタンスを参照します。各ゲーム要素は位置や入力イベントなどの一意のデータを保持しますが、可能な場合はデフォルトで共有データに設定されます。

オブジェクトが 2 つか 3 つあるだけでメモリの節約は目立たないかもしれませんが、共有データを編集する方が、手動で編集するよりも速く、エラーも少なくなります。

例えば、パドルの速度を変更する必要がある場合、1 か所で調整すると、すべてのシーンで両方のパドルが更新されます。MonoBehaviour に一意のフィールドとして格納している場合、1 回のクリックで 2 つの値が簡単に同期しなくなります。

ScriptableObject にデータをオフロードすることで、バージョン管理にも役立ち、チームメイトが同じシーンやプレハブで作業する際のマージ競合を防ぐことができます。

tab7

PaddleBallSO ゲームデータ

GameDataSO は、ScriptableObject をデータコンテナとして使用する方法を示しています。PaddleBallSO には、ゲームプレイを構成するさまざまな設定が含まれています。

  • パドルデータ:パドルスピード、ドラッグ、質量などの属性によって、ゲームプレイ中のパドルの動きと物理演算が決まります。
  • ボールデータ:これは、ボールの現在の速度、最大速度、バウンス乗数を保持し、シミュレーションと相互作用するときのボールの動作を制御します。
  • マッチデータ:GameDataSO には、試合中のポイント間の遅延に関する情報が含まれており、ゲームのペースを制御するのに役立ちます。
  • プレイヤー ID:PlayerIDSO ScriptableObject は、各プレイヤーのチーム ID として機能します(例:Player1 と Player2)。
  • プレイヤースプライト:これらのオプションのスプライトにより、プレイヤーのアバターをカスタマイズできます。
  • レベルレイアウト:LevelLayoutSO オブジェクトは、プレイヤーの開始位置とゴールや壁などのゲーム要素を定義します。

これらの設定とデータがすべて 1 か所にあるため、GameDataSO ではあらゆるオブジェクトがこの共有データにアクセスできます。これにより、これらのオブジェクトの管理方法が簡素化され、プロジェクト全体で一貫性が高まります。パドルの物理演算を変更しますか?複数のスクリプトを調整する代わりに、ここで 1 つの変更を加えます。

tab10

デュアルシリアライズの例:レベルレイアウト

時には、ケーキを食べて食べることもできます。デュアルシリアライズでは、データを ScriptableObject に格納しつつ、別の形式で維持することができます。

LevelLayoutSO スクリプトはこの概念を示しています。パドルとボールの開始位置を保持するだけでなく、壁とゴールのトランスフォームデータをカスタム構造体に格納します。

これらの値は、ExportToJson メソッドを介してディスクに書き込むことができます。JSON ファイルは人間が読めるテキストであり、Unity の外部で直接修正できます。これにより、エディターで ScriptableObject を操作し、JSON ファイルや XML ファイルなどの別の場所にデータを保存できます。

JSON や XML のようなファイル形式は、エディターでの作業が難しい場合がありますが、Unity の外部ではテキストエディターで簡単に変更できます。これにより、カスタムまたはユーザーが修正したレベルの可能性が広がります。

その後、GameSetup スクリプトは LevelLayout ScriptableObject または外部 JSON ファイルを使用してゲームレベルを生成できます。

カスタム修正したレベルを読み込むために、セットアップスクリプトは CreateInstance を使用してランタイムに ScriptableObject を生成します。次に、JSON ファイルからテキストを読み取り、ScriptableObject にデータを入力します。

カスタムデータによって ScriptableObject の内容が置き換えられ、この外部で変更されたレベルを他のレベルと同じように使用できるようになります。アプリケーションの他の部分は、スイッチを意識することなく正常に機能します。

Download PaddleBallSO
tab11

ScriptableObject データコンテナのその他の用途

パドルボールを使ったミニゲームでは、ScriptableObject データコンテナのすべてのユースケースを実演することはできませんが、ご自身のアプリケーションでは、以下のことを考慮してください。

  • ゲーム設定:定数やゲームルールなど、ゲームプレイ中に変更する必要のない設定パラメーターを考えましょう。これにより、他のコンポーネントはハードコードされた値を使用せずにこの設定データを参照できます。
  • キャラクターと敵の属性:ScriptableObject を使用して、体力、攻撃力、速度などの属性を定義します。これにより、デザイナーは開発者なしでゲームプレイ要素のバランスを調整できます。
  • インベントリおよびアイテムシステム:項目の定義や名前、説明、アイコンなどのプロパティは、ScriptableObject に最適です。また、インベントリ管理システムの一部として使用して、プレイヤーが収集、使用、装備するアイテムを追跡することもできます。
  • ダイアログおよびナラティブシステム:ScriptableObject には、ダイアログテキスト、キャラクター名、分岐するダイアログパス、その他のナラティブ関連のデータを保存できます。複雑な対話システムの基礎を築くことができます。
  • レベルと進捗データ:ScriptableObject を使用して、レベルのレイアウト、敵のスポーンポイント、目標、その他のレベル関連情報を定義できます。
  • オーディオクリップ:PaddleBallSO プロジェクトに示すように、ScriptableObject には 1 つ以上のオーディオクリップを保存できます。これらは、ゲームの複数の部分にわたってオーディオエフェクトや音楽を定義できます。
  • アニメーションクリップ:ScriptableObject はアニメーションクリップの保存に使用でき、複数のゲームオブジェクトやキャラクターで共有される一般的なアニメーションを定義するのに便利です。

ScriptableObject を深く掘り下げ、独自のプロジェクトに合わせて調整することで、さらに多くの応用例が見つかります。特にデータ管理に役立ち、さまざまなゲーム要素にわたって一貫性を維持しやすくなります。

スクリプタブルアウトロ

その他の ScriptableObject リソース

ScriptableObject によるデザインパターンの詳細については、e ブック「Create modular game architecture in Unity with ScriptableObjects」を参照してください。また、「ゲームプログラミングパターンによるコードのレベルアップ」では、Unity 開発の一般的なデザインパターンについて詳しく知ることができます。