本日はTickです。
ダニではないです。
タイマー管理だったりエラー監視などに用いられます。
では早速調べてみましょう。
【概要】
1フレーム毎に呼ばれるイベント。DeltaSecondsからフレーム単位時間を得ることができる。
公式ドキュメントはこちら。⇒
AActor::Tick
まぁ、大体はAActor継承のクラスだし、ってことでAActorのドキュメントを載せてます。
上記の例だとフレーム単位時間を出力します。結果はこう↓。
120fps出ているので、1/120 = 0.008333 で左のprint string出力はあってますね。
よって、0.008333秒間に1回呼ばれるわけです。簡単ですね。
こちらはタイマー管理を行う簡単なblueprintコードです。
変数TimerのDefault値に時間を仕込んでおけばTickで時間経過をカウントし、満了時にTimeUpイベントが呼ばれるわけです。
でもこれではタイマーが1度満了したあと、変数Timerがマイナス加算され続けて、ずっとTimeUpイベントが呼ばれることになってしまいます。
なので、タイマーの更新が必要かどうかのフラグ(bUpdateTimer)を設けてあげれば1度しかTimeUpイベントは呼ばれなくなります。これで解決。bUpdateTimerをtrueにしたタイミングでタイマーの更新が始まります。
もう一歩踏み込んでみると、こんな感じでしょうか。
BeginPlayイベントが完全に完了するまではタイマー更新しないようになりました。
BeginPlayの処理中にDelayを入れてタイミング調整したい場合などは、Gateでタイマー更新開始タイミングを抑制してあげれば安全になります。Begin処理にDelayを入れた場合、Tick更新が先に行われてしまうからです。なので、bUpdateTimerフラグとGateによる二段構えで、タイマーの更新を管理してあげるようになっています。先程のタイマー更新処理は「UpdateTimer」としてCollapsすれば、さらにコードがすっきりしますね。
簡単なTickを使ったコードでした。
ここからは応用編、いつものようにEngineコードにダイブします。
今日は追うのが中々大変でした。
・AActorクラスのTickって実は継承関数。実体はどこにある?
FTimerManagerクラスが本体。
・Tickって実はエディタ起動中(アプリケーションの実行中以外)も動作している説
動作している。Engineのふかーい所でwhileループをぐるぐる回し、Tick関数が呼ばれている。
ただし、World上に置かれたActor達はTick動作しない(UWorld::Tickは更新するけど、World上に置かれたActorは実行時にTick対象のActorがテーブルに登録され、それらのみTick処理を実行する)。
・Tickで得られるDeltaSeconds
デフォルトは1/30.0 = 0.03333が得られる。けど、フレーム毎にDeltaSecondsが更新される。
で、実は制限がある。UWorld::Tickにしれっと記述があったが、「2000 fps ~2.5 fps (0.0005f ~ 0.40f)」がWorld以下で得られるDeltaSecondsとなっている。上限の2000fpsは置いといて、下限の2.5fpsは最低でも保障されるというわけね。
ここの記述に関してはMathクラスのClampを使用しているので注意。
・Delayを制御する
コンソールコマンド”slomo XX” (XXはfloat型数値) でDeltaSecondsを制御できる。
DeltaSeconds = DeltaSeconds * XX となるので、"slomo 10.0"と入力すれば10倍速になる。
逆もまたしかり、小数値を入力することでスローモーションを簡易的に実現できる。
さて、総括。
Tickについては、フレーム単位時間を得られるってことを抑えておけば問題ないので、
それ以外は補足程度に頭の片隅にしまっておこう。