あるオブジェクトが動作を終了したタイミングで、他のオブジェクトが動作を開始するような処理を実装する場合に、どのような方法を思いつくだろうか?
アニメーションであれば、アニメーションのタイムライン上にイベントを設定して、別な処理を割り付けて、ということは可能
では、上記ではなく、スクリプト内のある処理の実行が終了したことを、別のオブジェクトに通知したいような場合はどうするか?
例
オブジェクトA :処理を実行し、終了したらオブジェクトBに通知
オブジェクトB :ある処理を実行
〇実装案
オブジェクトAは処理が終了したらフラグを立てる
オブジェクトBは、Update関数内からオブジェクトAの終了フラグを毎フレームチェックする
上記は、Update関数で毎フレーム監視するというのは効率が良くないし、フラグが別の処理で更新されたりしたらややこしいことになりそう
できれば、処理が終了した時にイベントを発生させて、オブジェクトBの処理を呼び出したいところ・・・
ということで、ググっていたら、良い方法が見つかったので書き残しておくことにする
〇UnityEventを活用して、カスタムのイベントを発生させる
テスト的に作ってみたのがこれ!!
①スタートボタンを押すと、スクリプトAが三秒間のカウントダウンを開始
②終了したらイベント発動
➂スクリプトBのテキストの更新処理を呼び出す
オブジェクトA///////////////////////////////////////////////////////////////////
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events; //イベントを使用する場合はこいつが必要
public class AManager : MonoBehaviour
{
[SerializeField] Text Msgtext;
float counter = 0;
[SerializeField] UnityEvent customEvent; //インスペクターで割り付けられるようにする
public void CountDownStart()
{
StartCoroutine(Countdown(3f));
}
IEnumerator Countdown(float duration)
{
counter = duration;
while (counter > 0) {
counter -= 0.05f;
Msgtext.text = "スクリプトA 実行中" + counter.ToString("f3");
yield return new WaitForSeconds(0.05f);
}
Msgtext.text = "スクリプトA 終了";
yield return new WaitForSeconds(1f);
Msgtext.text = "スクリプトA イベント発動";
customEvent.Invoke(); //処理が終了したのでイベントを発動
}
}
オブジェクトB///////////////////////////////////////////////////////////////////
using UnityEngine;
using UnityEngine.UI;
public class BManager : MonoBehaviour
{
[SerializeField] Text textB;
public void UpdateText()
{
textB.text = "スクリプトB : イベントを受信";
}
}
インスペクタ上でイベントが発生した時に実行するオブジェクトBの処理を割り付け
本当にUpdate関数で監視するより処理負荷が低いかは定かではないが、スクリプトがわかりやすく、処理の流れも一方向のため、間違えは起きにくそうな印象
10/23追記
上記のままだと、イベントを発生させるまでもなく、オブジェクトBの関数を呼び出すだけでよいのでは、という疑問がわくところ
このようなイベントが役に立つのは、オブジェクトBの関数を呼び出すオブジェクトが複数あり、呼び出し元毎に処理を変えるような場合だ
public void UpdateText(int index)
{
switch(index){
case 0:
textB.text = "スクリプトB : オブジェクト0からイベントを受信";
break;
case 1:
textB.text = "スクリプトB : オブジェクト1からイベントを受信";
break;
}
今回は以上