タイマー割り込みみたいなものがないかと思って調べたのでメモ。
実装したいタイマー割り込みは、
- 設定されている時間が経過したら、設定されているまたは特定のメソッドを呼び出す
- 時間と呼び出し先は複数設定可能
- 時間と呼び出し先は任意のタイミングで処理リストから外せる
といったところ。
UE4の場合
UE4のタイマーは、TimerManager.SetTimerを利用する。(ブループリントからも利用可)
FORCEINLINE void SetTimer(
UserClass* InObj,
typename FTimerDelegate::TUObjectMethodDelegate< UserClass >::FMethodPtr InTimerMethod,
float InRate,
bool InbLoop = false,
float InFirstDelay = -1.f)
一番基本になるSetTimerの説明。(ソース内のコメント)
- 指定されたnative関数を指定された間隔で呼び出すようにタイマーをセットする
- もし、タイマーが既にdelegateに設定されているならば、新しいパラメータを設定して経過時間を0に再設定する。(タイマーを再起動する)
引数リストは、こんな感じ。
InObj : タイマー関数がONになったとき呼ばれるオブジェクト
InTimerMethod : タイマーの時間が来たときに呼ばれるメソッド
InRate : 設定から動作するまでの時間。0以下では既存タイマーをクリア
InbLoop : Trueなら一定間隔で動作させる、falseなら一度だけ起動
InFirstDelay : 最初にタイマーが動くまでの待ち時間。マイナス値ならば、InRateを使う
Delegateを使うものはもう少し定義が簡単。(内部でDelegateの設定をしないから)
FORCEINLINE void SetTimer(
FTimerDelegate const& InDelegate,
float InRate,
bool InbLoop,
float InFirstDelay = -1.f)
SetTimerは、InternalSetTimerを呼び出すだけ。
Delegateを使う場合は、TimerManagerTests.cppのTimerManagerTest_ValidTimer_Delegateを参考にする。
// void FTimerManager::InternalSetTimer(
// FTimerData& NewTimerData,
// float InRate,
// bool InbLoop,
// float InFirstDelay )
FTimerDelegate Delegate;
Delegate.BindRaw(&Dummy, &FDummy::Callback);
Delegateは(呼び出すクラス, 呼び出すメソッド)の形で設定する。
Unityの場合
- CoRoutineを…とか書いてあることが多い。(よくわからない)
- DeltaTimeを使って、毎f呼び出されている間に実時間を測る(実処理時間)
- MonoVehaviour.Invokeを使う(秒単位なら)
一番やりやすそうなのは、自分でクラスを作って時間と呼び出し先を管理する方式。
これは、UE4のTimerManagerの実装にも近いはず。
初期化の際にDelegateを受け取って、リストに登録する→経過時間を調べて呼び出すみたいなの。
C#にもDelegateという仕組みがあるのでそれを使うと呼び出しイベントの管理はやりやすそう。
delegate前置詞を置いた変数に関数を設定する。(Cの関数変数みたいなかんじか)
delegate void delegatefunction();
引数リストも宣言すれば引数を取れる。
.NETのC#では、スレッドセーフな関数呼び出しのためにInvoke(Control.Invoke)というメソッドがある。
MonoBehaviour.Invokeは、メソッドと呼び出し待ち時間を指定して、待ち時間が終わったらそのメソッドが呼ばれる。
UnityEvent.Invokeだと引数なしで、登録されているコールバックをすべて実行するらしい。