6. セットアップ手順(図解つき)

CGS をあなた自身のアセットに接続する任意のレシピ集 — オーディオミキサー、入力アクション、IL2CPP link.xml、Addressables。

この章の内容は、フレームワークを使い始めるうえで何ひとつ必須ではありません — すべては最初からそのまま動きます。ここでの手順は、フレームワークをあなたのアセットに接続するものです: あなたのオーディオミキサー、あなたの入力バインディング、あなたのビルド設定、そして(任意で)Addressables です。各手順は、上から下までそのままなぞれる完全なレシピになっています。

6.1 自分のオーディオミキサーを使う

オーディオサービスにはミキサーが同梱されているため、サウンドは最初から鳴ります。自分の Unity AudioMixer アセットを使う準備ができたら、そのミキサーには 2 つのものが必要です:

  1. Master の下に、正確に MusicSfxVoice と名づけた 3 つのグループ。 オーディオサービスは、各チャンネルを同じ名前のグループへルーティングします。
  2. 音量用の 4 つの公開 float パラメーター、名前は MasterVolumeMusicVolumeSfxVolumeVoiceVolume。パラメーターを公開するには、グループを選択し、Inspector で Volume フィールドを右クリックして "Expose ... to script" を選びます。名前の変更は、ミキサーの Exposed Parameters ドロップダウンで行います。

必須の 3 グループと公開パラメーターを示す Audio Mixer ウィンドウ

Master の下に必須の 3 グループ(Music、Sfx、Voice)を持つ Audio Mixer ウィンドウ。Exposed Parameters ドロップダウン(右上)には、4 つの音量パラメーター MasterVolume、MusicVolume、SfxVolume、VoiceVolume が並んでいる必要があります。

次に、最初のシーンに置く小さなスクリプトで、あなたのミキサーをフレームワークに渡します。このスクリプトは、あなたのミキサーを土台に新しいオーディオサービスを構築して差し替えます:

using CommonGameSystem.Core;
using UnityEngine;
using UnityEngine.Audio;

[DefaultExecutionOrder(-100)] // swap before other scripts cache the audio service
public sealed class AudioSetup : MonoBehaviour
{
    [SerializeField] private AudioMixer gameMixer; // assign your mixer in the Inspector

    private void Awake()
    {
        var options = AudioOptions.Default;
        options.Mixer = gameMixer;
        // Used different parameter names? Point the service at them:
        // options.masterParam = "MyMasterVol";

        var previous = ServiceLocator.Resolve<IAudioService>() as System.IDisposable;
        ServiceLocator.Replace<IAudioService>(new AudioService(
            ServiceLocator.Resolve<IConfiguration>(),
            ServiceLocator.Resolve<IEventBus>(),
            ServiceLocator.Resolve<IObjectPoolService>(),
            ServiceLocator.Resolve<ITimeService>(),
            options));
        previous?.Dispose(); // removes the old service's hidden helper object
    }
}

オプションメニューの音量スライダーは、ミキサーと直接ではなく、設定サービスと対話します。Get<AudioSettings>() で現在のグループを読み取り、フィールドを変更し、Set(...) に続けて FlushPending<AudioSettings>() を呼びます。フラッシュは変更を保存し、新しい音量を即座にミキサーへ反映します。完全なリファレンス: AudioConfiguration

6.2 自分の入力アクションを接続する

入力サービスは、あなたが作成する Unity Input System アセット(.inputactions ファイル)を読み取ります — フレームワークが同梱するのは空のプレースホルダーだけです。アクションマップ("Gameplay"、"Menu")とその中のバインディングを定義するのは、あなたのアセットです。

  1. アセットを作成します: Project ウィンドウで右クリックし、Create > Input Actions を選びます。GameInput のような名前をつけます。
  2. アセットを開き、アクションマップとアクションを追加します — 例えば "Move" と "Jump" を持つ "Gameplay" マップです。
  3. フレームワークの UI パネルスタックを自動入力切り替えつきで使うなら、正確に ui.panelui.modal という名前のマップも 2 つ追加してください。パネルスタックは、メニューが開いている間これらを有効化します。名前は大文字と小文字を区別します。

Gameplay マップとパネルスタック用の 2 つのマップを表示した Input Actions エディタ

"Gameplay" マップと、パネルスタック用の 2 つのマップ ui.panel・ui.modal(ハイライト表示)を持つアセットを表示した Input Actions エディタ — これが目指す完成形です。フレームワークがこのアセットを編集することはありません — デッドゾーン、ホールド、バインディングは完全にあなたの管理下に残ります。

最初のシーンに置く 1 つのスクリプトでアセットを接続します。このスクリプトは、あなたのアセットを土台に入力サービスを再構築し、メニューナビゲーションもそれを使うようにパネルスタックを再構築します:

using CommonGameSystem.Core;
using UnityEngine;
using UnityEngine.InputSystem;

[DefaultExecutionOrder(-100)] // swap before other scripts cache these services
public sealed class InputSetup : MonoBehaviour
{
    [SerializeField] private InputActionAsset actions; // your .inputactions asset

    private void Awake()
    {
        var source = new HardcodedInputKeyMapSource(actions);
        var bus  = ServiceLocator.Resolve<IEventBus>();
        var time = ServiceLocator.Resolve<ITimeService>();

        var oldInput = ServiceLocator.Resolve<IInputService>() as System.IDisposable;
        var oldUi    = ServiceLocator.Resolve<IPanelStack>()  as System.IDisposable;

        ServiceLocator.Replace<IInputKeyMapSource>(source);
        var input = new DefaultInputService(source, bus);
        ServiceLocator.Replace<IInputService>(input);
        ServiceLocator.Replace<IPanelStack>(
            new PanelStack(bus, input, time, PanelStackOptions.Default));

        oldInput?.Dispose();
        oldUi?.Dispose();
    }
}

パネルスタックを使わない場合は、2 つの IPanelStack 行と oldUi の行を削除してください。あなたのスクリプトが独自のアセンブリ定義に属している場合、このスクリプトには CommonGameSystem.InputCommonGameSystem.UIUnity.InputSystem への参照が必要です — 第 7.1 章の表を参照してください。

再起動をまたいで維持されるリバインド。 プレイヤーがコントロールを割り当て直したら(サービスの対話的リバインドが、新しいキーを押す手順をプレイヤーに案内します)、その後に SaveBindingOverrides() を呼んでください。オーバーライドは Unity の PlayerPrefs に保存されます。起動時に一度 LoadBindingOverrides() を呼んで復元し、「デフォルトに戻す」ボタンには ResetBindingOverrides() を使います。完全なリファレンス: Input

6.3 IL2CPP ビルド: セーブ用クラスを生かしておく (link.xml)

IL2CPP ビルドは、ゲームを小さくするために、未使用に見えるコードをストリップします。シリアライズを通じてのみ生成されるクラス — セーブデータ、カスタム設定グループ、シリアライズするイベントクラス — は、ストリッパーには未使用に見えてしまいます。その結果: エディタではセーブが機能するのに、ビルドしたゲームでは静かに壊れます。

修正は link.xml ファイルです。これは Unity に「これらは決してストリップするな」と伝えます。Assets/ 配下の任意の場所(フォルダのルートで構いません)に、正確に link.xml という名前のファイルを作成し、自分のクラスを列挙します:

<linker>
  <assembly fullname="Assembly-CSharp">
    <type fullname="MyGame.PlayerSave" preserve="all"/>
    <type fullname="MyGame.OptionsSave" preserve="all"/>
  </assembly>
</linker>

このファイルはどこに置く? Assets/link.xml として保存してください。各 <type> 行は、あなた自身のクラスを完全な名前空間つきで指定します。"Assembly-CSharp" はプロジェクトスクリプトのデフォルトアセンブリです — コードがアセンブリ定義を使っている場合は、そのアセンブリ名を代わりに使ってください。

経験則:

  • Save<T>(...) に渡すクラス、または設定グループとして保存するクラスごとに、<type> 行を 1 つ追加します。
  • fullname名前空間を含むクラス名です。ここでのタイプミスは静かに失敗するので、コードからコピーしてください。
  • フレームワーク自身の型はすでに保護されています。列挙するのはあなたのクラスだけです。
  • これは IL2CPP ビルドだけに影響します。エディタと Mono ビルドはストリップを行わないため、このバグは実ビルドまで潜伏します。

6.4 Addressables のセットアップ(アドレスでアセットをロードする場合のみ)

Unity の Addressables パッケージを必要とするサービスは 2 つです: アセットプロバイダー(プレハブ、スプライト、オーディオをテキストのアドレスでロードし、参照カウントを自動管理)と、Addressable シーンサービス(Addressables からの加算シーン)です。どちらも使わないなら、この節はスキップしてください — フレームワークはこのパッケージなしでも問題なく動きます。

  1. Window > Package Manager の Unity Registry タブから Addressablescom.unity.addressables)をインストールします。
  2. Window > Asset Management > Addressables > Groups を開き、Create Addressables Settings を一度クリックします。
  3. 実行時にロードしたいアセットを選択し、Inspector 上部の Addressable にチェックを入れます。チェックボックスの隣のテキストフィールドが、そのアセットのアドレスです。
  4. そのアドレス文字列が、フレームワークに渡すキーになります: await assets.LoadAsync<GameObject>("characters/player")

エディタでは、Play モードは Addressable アセットをプロジェクトから直接ロードするので、自由にイテレートできます。プレイヤービルドを出荷する前に、Groups ウィンドウから Addressables コンテンツを一度ビルドしてください(Build > New Build > Default Build Script)。パッケージがインストールされていれば、両サービスは起動時に自動で登録されます — フレームワーク側の追加セットアップはありません。


次へ: 7. フレームワークをプロジェクトに合わせて調整する