【UE4】エモノを食って飛び去るドラゴン/第13回UE4ぷちコン進捗 - 2020/03/22


株式会社ヒストリアさん主催の第13回UE4ぷちコンの作業進捗。

作業をしながらおやつを食べすぎて、晩飯はまだ欲しくない。
…ので、進捗記事を書いておこう。(これが終わったら晩飯にしよう)

引き続き、敵となるドラゴンを作っている。
前回の飛来の続きとなる、エモノに食らいついて飛び去るような挙動を作成した。

例によって、本プロジェクトとは別の、実験用のプロジェクトで作っている。

こんな感じになった

  • 【左手前】標準位置となるであろう距離での食らいつき実験。
  • 【中央】横に振ったら変に見えるかどうかの実験。(アリだと判断)
  • 【右奥】これは遠すぎるだろう、という距離での実験(さすがにナシ。残像見えてるし)

まあ、動きが速すぎて、どれもズルい感じもしなくもない。

ゲーム本編ではドラゴンは1匹の予定。

食らいつきについて

食らいつき判定がでたら(今回はゲームパッドのボタンを押したら)、まずはエモノの位置から逆算した、食らいつき Transform を算出する。
これが昨日ハマっていた、Construction Script でのあれこれである。結局は、愚直に Tick を回して Print String でログに計算結果を出して、その数値をコピペして使っている。

次のフレームからは、その Transform に向かってホーミング。
Ease ノードの Ease Out を使用。(出だしが早く、だんだんゆっくりになる挙動)

この Ease ノードの使い方、おそらく誰もやっていないだろう的なトリッキーな方法。
通常、Alpha は変数で持っておいて、Tick か何かで

Alpha = Clamp(Alpha + AlphaSpeed * DeltaSeconds, 0.0f, 1.0f);

的な計算をするはず。一方、このやり方は、

Alpha = DeltaSeconds / ConvergeSeconds;

…とただDeltaSecondsを定数ConvergeSecondsで割っているだけで、Ease用の変数 Alphaを持つ必要がない。ちなみに、このConvergeSecondsは「収束するまでの秒数」の意。つまり、ConvergeSeconds の秒数で目標値に追いつくことになる。

このアイデアは、大昔の固定フレームレートの時代にやっていた

void SomeObject::Tick()
{
    CurrentValue = Lerp(CurrentValue, TargetValue, 0.9f);
}

みたいな、毎フレーム 90% の割合で目標値(TargetValue)に近づけるやり方=残り距離の10%ずつ近づけるやり方を、可変フレームレートの世界に持ち込もうとして作ったもの。

大雑把には:

  • 毎フレーム 0.9 倍というやり方は、等比級数と同じ挙動をするよね。
  • 等比級数の極限をとると、exponential の曲線になるよね。
  • 極限をとるということは、連続系(=可変フレームレート)の世界で使える式になるよね。
  • そういえば、Ease は exponential 曲線だよね。
  • まじめに数式を解くのが面倒なので、Ease 使えばいいんじゃね?

という考えで編み出したもの。私の好みの挙動をするので多用している。

【注意】全く厳密な計算ではないので注意。似ているから Ease を使っているだけ。なので、ConvergeSeconds で指定した時間でちゃんと収束するわけでもないし、フレーム落ちの影響を受けたりしてしまう。とはいえ、可変フレームレートの世界で毎フレーム 0.9 を掛けるようなやり方よりは、フレーム落ち時の暴れ方は穏やか。

もし、フレームが安定しないアプリになってしまったり、ヒッチが多くなってしまったりしたら、あらかじめ DeltaSeconds = Clamp(DeltaSeconds, 1/90, 1/45) などして、例えば DeltaSeconds = 1.00(秒) みたいな極端な値にならないように誤魔化すのも手。

咥えて(くわえて)連れ去る周り

噛みつきアニメーションに「BiteAlpha(食いつきアルファ)」のカーブを用意。

0なら咥えてない、1なら咥えている、を表すためのもの。
これで、エモノの Transform を、現在の位置から、口の中の位置まで Lerp している。
で、一度咥えたら(1に達したら)、

  • エモノActorを消して、ドラゴンがあらかじめ持っているエモノコンポーネント(=Skeletal Mesh Component) を表示する。
  • あとは、ずっと口の中の Transform にする。

飛び去る

これは単純にアニメーションを再生しながら、World Up 方向に Add Force しているだけ。
一定の高度に達したら Destroy Actor する。

とりあえず、現状はこんな感じ。
…さて、晩飯に取り掛かるとするか。