空気清浄機
新しく購入した空気清浄機の前でおならをしたらランプが真っ赤になって軽くショックを受けた皆さんこんにちは。自分の放屁がランプを真っ赤にするほど空気を汚すとは知りませんでした。以後気を付けます。
ソニックフロンティア
当初は購入予定ではなかったのですがネットの評判が良かったので購入しました。
従来のステージクリア型のソニックからオープンワールドに変わった本作ですが、私のような濃いソニックファンではないカジュアルなユーザには非常に楽しい内容になっていると思います。
これまでオープンワールドゲームと言えば自由なシナリオ進行と探索の深さを楽しむ物が主流となっていましたが、『Marvel's Spider-Man』の発売を契機として最近ではフィールド間の移動を楽しむ事に重点を置いたゲームがオープンワールドの一つの支流として確立されつつあり、『ソニックフロンティア』はこの支流に沿ったゲームであるといえます。
フィールド内に点在するチェックポイントのギミックを解除⇒従来型ソニックのステージをクリア、というゲームフローですが、ソニックらしい高速走行とレールライド、ピンボールジャンプ等のギミックによる空間移動は爽快感がありそれだけで楽しいため、ストーリーを追わずにただフィールドを彷徨うだけでも時間を忘れて遊ぶことが出来ます。
妙にフォトリアルよりなグラフィックで敵のデザイン(特にカラーリング)が地味だという事と、やけに中二病っぽい台詞回しは気になるところですが、それを上回るぐらいソニックの操作が楽しく爽快感が得られるゲームだと思います。
デザインパターン講座4回目
Unity公式から公開されているデザインパターン学習用のサンプルプロジェクト
各デザインパターンがディレクトリ別に格納されています。
今回はそのサンプルプロジェクトに関する解説4回目、「8 Singleton」になります。
前回まで解説は以下
Singletonパターン
このパターンを簡単に説明すると、生成するインスタンスの数を1つに制限した設計パターンと言えます。
RPGなどのゲームを例にとると、プレイヤーのキャラクターやNPC、敵といったキャラクターはゲーム内で多数存在するため、その分それを制御するクラスは複数必要ですが、ゲーム全体の運行を管理する神視点のクラスは複数存在するとかえって処理が煩雑になり、後々のバグの原因となのでゲーム内に一つだけ存在する方が望ましいです。
この「ゲーム内に1つしか存在」を実現し、かつ保証する組みがSingletonパターンとなります。
サンプルシーン
「8 Singleton」配下には以下のようなファイルが格納されています。
そして、ここに格納されているサンプルシーン「Singleton」を実行してみるとこんな動作をします。
ゲーム実行前は複数あったスピーカーのオブジェクトが一つになり、クリックによりそのスピーカーから音が鳴ります
(動画では音がないため、スピーカーを揺らす処理を行っています)
各スピーカーにはそれぞれSingletonを継承したAudioManagerクラスがアタッチされており、起動時に各自インスタンスを生成しようとしますが、既に自身以外のSingletonインスタンスが存在する場合は生成を行わず、逆に自身を削除(Destory)しています。
これによりゲーム開始から最も先にインスタンスを生成したスピーカーのみが残り、「ゲーム内に1つしか存在」が見た目は実現します。
private void RemoveDuplicates() { if (_instance == null) { _instance = this as T; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } }
唯一の存在を保証する
上記の処理によりゲーム開始時に「ゲーム内に1つしか存在」が見た目は実現できましたがこれだけでは不十分で、外部からの新規作成・コピーの禁止を保証して、ゲーム開始以後も「唯一の存在」が壊れない仕組みを実現する必要があります。
この為、Singleton(ゲーム内に1つ)となるクラスは以下のルールに準拠して製造する必要があります。
- 自身の型のインスタンスが privateなクラス変数として定義されている
- 外部から生成されないようにprivateにしている
- インスタンスを返すためのクラス関数が定義されている
サンプルシーンのSingletonクラスではこれらのルールが以下の形で実装されています。
1.自身の型のインスタンスが privateなクラス変数として定義されている
private static T _instance;
2.外部から生成されないようにprivateにしている
private static void SetupInstance() { // lazy instantiation _instance = (T)FindObjectOfType(typeof(T)); if (_instance == null) { GameObject gameObj = new GameObject(); gameObj.name = typeof(T).Name; _instance = gameObj.AddComponent<T>(); DontDestroyOnLoad(gameObj); } }
3.インスタンスを返すためのクラス関数が定義されている
public static T Instance { get{return _instance;} }
上記の対応によりSingletonのクラスは自分自身のインスタンスをグローバルなstaticメンバとして持ちます。
この為、他クラスからSingletonのクラスの関数を呼び出す場合は、
クラス名.Instance.関数
の形で呼び出すことができるのでかなり便利になります。
MonoBehaviourを継承しよう
UnityでSingletonパターンを採用したクラスを作成する場合はMonoBehaviourを継承したクラスをSingleton化する方が色々便利です。
この為、サンプルシーンでは以下のような形でMonoBehaviourを利用しています。
・MonoBehaviourを継承したクラスをSingletonクラス
public class Singleton<T> : MonoBehaviour where T : Component { private static T _instance; public static T Instance { if (_instance == null) { _instance = (T)FindObjectOfType(typeof(T)); if (_instance == null) { SetupInstance(); } else { string typeName = typeof(T).Name; } } return _instance; } }
・Singletonを継承したGameManagerクラス
public class GameManager : Singleton<GameManager> { }
まとめ
Singletonパターンとは生成するインスタンスの数を1つに制限した設計パターンです。
Singletonクラスは外部からの生成・コピーを禁止し、自分自身のインスタンスをグローバルなstaticメンバとして持ちます。
Untiyで利用する場合はMonoBehaviourを継承したクラスをSingleton化しましょう。