イベントを使うことでプログラム同士の処理をそれぞれ分けて作成することができます。反面、プログラムとして気をつける部分も出てきますのでサンプルを見ながら注意点をおさえて利用しましょう。使いこなせると強力な武器になります。
イベントを使うとどんな実装になる?シンプルなサンプル
主に何らかのインタラクションを起こすとき(ボタンを押したりユーザーの操作を起こしたとき)、それによって何らかの操作が発生します。シンプルな作りのときはいいですが、プロジェクトが大きくなってくるとコードが複雑化しやすくなります。イベントを利用することで分かりやすく実装することができます。
サンプルプログラム
まずはイベントを使った基本的な実装例として、クリックされたときlocalScaleが2倍の大きさになるプログラムを例にあげます。イベントを監視するEventManagerとサイズ変更を行うChangeSizeスクリプトの2つを利用します。
using UnityEngine;
using System;
public class EventManager : MonoBehaviour
{
public static event Action ExampleEvent;
private void Update()
{
if(Input.GetMouseButtonDown(0))
{
/*
if(ExampleEvent != null)
{
ExampleEvent.Invoke();
}
*/
ExampleEvent?.Invoke();
}
}
}
using UnityEngine;
public class ChangeSize : MonoBehaviour
{
private void OnEnable()
{
EventManager.ExampleEvent += IncreaseSize;
}
private void OnDisable()
{
EventManager.ExampleEvent -= IncreaseSize;
}
private void IncreaseSize()
{
Debug.Log("Called.IncreaseSize");
transform.localScale = new Vector3(2, 2, 2);
}
}
EventManagerのコメントアウト部分はなに?
通常インスタンスなどに対してアクセスする場合Nullチェックなどが必要になりますが、イベントに対しては?マークをつけることでNullチェックと同様の機能が発揮されます。コードの短縮にもなるので、必要に応じて使っていきましょう。
Unity側の設定
今回はローカルスケールを倍にしているのでSpriteでもImageでもCubeでも見えるものであれば何でも大丈夫です。新しいシーンを用意して、以下の準備をしてください。
倍の大きさにするもの
ここではスプライトを用意します
- ヒエラルキーを右クリックして2D Object/Sprites/Square
- 作られたSquareにChangeSizeスクリプトをアタッチ
- 位置をカメラの見える位置に調整(デフォルトだと0,0,0で見えるはず)
EventManagerを用意
カメラなどにスクリプトを貼り付けても大丈夫ですが、明示的に個別のGameObjectを与えましょう。
空のGameObjectにEventManagerスクリプトをアタッチします。
動作確認
ゲームを動かしてみて、実際にクリックしてみるとスプライトが大きくなったと思います。
使用方法を踏まえてのプログラム的な解説
上記プログラムの実装的な部分を踏まえて解説します。
イベントを仲介する変数について
using System;
public static event Action ExampleEvent;
下記部分がEventManagerとChangeSizeを仲介する変数として利用されています。今回は引数を使っていないため、各メソッドにも引数を用いてません。
変数はstaticで宣言されているためEventManager.ExampleEventでアクセスすることが可能です。またeventやActionを使うには「using System;」が必要です。
イベントを発生させる処理
ExampleEvent?.Invoke();
イベントを起こすにはInvokeを利用します。今回だとEventManager側で左クリックをされたタイミングで呼ばれます。
Invoke()は引数が不要なパターンで、引数を必要とする場合はInvoke(引数)という感じになります。
イベントを呼ばれた方の実装
登録部分
EventManager.ExampleEvent += IncreaseSize;
解除部分
EventManager.ExampleEvent -= IncreaseSize;
IncreaseSizeメソッドの引数はExampleEventと一致する必要がある
private void IncreaseSize()
{
Debug.Log("Called.IncreaseSize");
transform.localScale = new Vector3(2, 2, 2);
}
今回だとChangeSizeクラス側。ExampleEventが呼ばれたら登録したメソッドを呼んでもらうことになります。
このとき注意したいのはIncreaseSizeメソッドの引数がExampleEventと一致している必要があります。
イベントを実践で使うときの注意点
実際にクリックして大きくなったのを確認できましたでしょうか?イベントを扱う際に注意したいポイントがありますので下記の内容には注意してください。
イベントの登録と解除はペアで行う
先程のプログラムの中で、ChangeSizeのStartメソッド内でExampleEventが呼ばれたときにIncreaseSizeメソッドの呼び出しに連動するように関連付けが行われています。
EventManager.ExampleEvent += IncreaseSize;
今回のプログラムであれば問題ありませんが、ゲームによってはイベントを受けたいタイミングとそうではないタイミングがあります。もうこれ以上イベントを呼ばれたくない場合はマイナスイコール(-=)を使って解除を行いましょう
EventManager.ExampleEvent += IncreaseSize;
OnEnableとOnDisableはゲームオブジェクトがアクティブ・非アクティブになるたびに呼ばれます。ここでペアにしておくともれなくイベントを受け取ったりすることができます。
多重に登録しないようにする
ペアで登録と解除を行うように注意する点がありましたが、それと似たような現象として、多重に登録を行わないようにするということも注意が必要です。例えば下記のようになっているとします。
private void OnEnable()
{
EventManager.ExampleEvent += IncreaseSize;
EventManager.ExampleEvent += IncreaseSize;
}
この状態でマウスをクリックすると1度のクリックで2回ログが呼ばれます。ゲーム画面的には2倍になったものがもう一度2倍になっても変化がありませんがデバッグログの方ではその違いがはっきりと出ます。
ゲームの状況によって登録と解除が何度も行ったり来たりする場合、どこかの拍子に登録が重複すると思いもよらないような回数呼ばれてしまうことがあります。よくあるのやキャラの動き関係が2倍動き出すとか何かを繰り返したあとに操作すると変になるとかです。
コメント