PaperSloth’s diary

主にゲーム開発関連についての記事を書きます。

UE4 ヒットストップの実装について

※1点修正があったため追記しました。(2018/01/31 1:22)
詳しくはページ下部をご覧ください。

環境

Unreal Engine 4.17.2

Time Dilationについて

ヒットストップの実装に関してはGlobal Time Dilationの値を変更するだけで簡単に実装ができます。
Time Dilationの説明について特に知る必要がないという人は読み飛ばしてください。

ここではTime Dilationの種類等について解説します。
Time Dilationは初期値が1.0です。
デフォルトの設定では
最小値は0.0001
最大値は20.0
となっています。
1を超える値を設定した場合、例えば2.0の場合は2倍速になることを表しています。
逆に1未満の場合、例えば0.5の場合は通常の1/2の速度になることを表しています。

基本的には下図のようなCustom Time DilationとGlobal Time Dilationを使用します。
f:id:PaperSloth:20180128231743p:plain

Custom Time Dilationとは

Custom Time DilationはActorに設定されたActorごとの速度を表します。
定義は下記のActor内に記述があります。
Engine/Source/Runtime/Engine/Classes/GameFramework/Actor.h
Engine/Source/Runtime/Engine/Private/Actor.cpp

Actorの更新呼び出しの中で
下図のように使用されています。

Target->TickActor(DeltaTime * Target->CustomTimeDilation, TickType, *this);	

Global Time Dilationとは

これは名前にGlobalとあるようにゲーム中の更新に関わります。
定義箇所は下記です。
Engine/Source/Runtime/Engine/Classes/GameFramework/WorldSettings.h
Engine/Source/Runtime/Engine/Private/WorldSetting.cpp

因みにC++側で使用する際はほとんどの場合では
代わりにGetEffectiveTimeDilationを使用してください。という警告があります。

先程最小値は0.0001で最大値は20.0と書きましたが、この設定は変更することが出来ます。
f:id:PaperSloth:20180128232843p:plain

World Setteingsタブの最下部に隠れたパラメーターとして
Min Global Time Dilation, Max Global Time Dilationがあります。
BlueprintからSet Global Time Dilationを呼び出した際にはこの値を参照してClampされています。
そのため、厳密には0を指定しても0.0001が設定されるため、完全に更新が停止するというわけではありません。

ヒットストップの実装

前置きが長くなりましたが、ヒットストップの実装は至って簡単です。
今回はMacroLibraryとして作成したものを例に紹介します。
親クラスにはActorを指定しています。

実装にはたった5つのノードを呼び出すだけの非常にシンプルな実装となっています。
f:id:PaperSloth:20180128233845p:plain

図に説明があるように
Global Time Dilationにどれくらいゆっくりにしたいかの値を設定します。
0以上1未満の値でゲーム全体をゆっくりにすることが出来ます。

次にDelayで元の早さに戻るまでの時間を設定します。

呼び出し例としては下記のような感じです。
ここではわかりやすくするためにDelayに渡す値をStop Timeという名前にしています。
通常の1/10の速度に変更し、0.15秒後に元の早さに戻るように設定しています。
※0.15秒ではなく、1.5秒後になります。
詳しくは追記したページ下部の説明をご参照ください。
f:id:PaperSloth:20180128234145p:plain

実際にヒットストップを使用した感じは下記のような感じになります。
ここでは敵の撃破時に使用しています。
容量の都合上、10FPSのGifで分かりにくいですが、こんな動きになります。
f:id:PaperSloth:20180130223753g:plain

※1点誤りがあったため、追記です。
ブログ公開後に指摘をいただきましたように
Delayノードも時間の進みが遅くなります。

これは最初、気付かずに実装すると少しハマってしまうので注意が必要です。
Global Time Dilationの影響を受けるノード
・Delay
Global Time Dilationの影響を受けないノード
・Set Timer by Event


以上のように5つのノードだけで簡単にヒットストップが実装できます。
先程の例のようにMacroLibraryにしておくと便利です。
その時はActor以上を継承したものを選択しましょう。
また、FunctionLibraryでは実装できません。
理由としてはDelayなどのLatentノードの呼び出しができないからです。
ゲームのコンボや撃破時の演出など活用できる場面は幾つかあると思います。
是非試してみてください。