PavilionDV7の雑多なやつ

Qiitaから移行しました。UE4に関する記事から興味のあることまで色々書きます。

【UE5】Box Collisionを使ってドラッグ&ドロップで範囲指定する

はじめに

第19回ぷちコンに提出したゲームではBox Collisionを利用してドラッグ&ドロップで拘束魔法の範囲を指定できる仕様を実装した。この記事ではその実装方法を紹介する。(ドラッグ&ドロップは以降「D&D」と書く)

拘束魔法の範囲指定の様子は次の動画で。

youtu.be

実装開始

まずは基礎部分

実装するブループリントは「Pawnクラス」を継承したブループリントとする。

コンポーネントはルートに「Box Collision Component」を設定したのみ。プロパティはいじらない。


D&Dの開始・終了地点の取得には「Get Hit Result Under Cursor by Channel」を使用する。その関数からヒット位置のみを取り出す関数を作成する。この関数は純粋関数(Pure)にしている。

続いてカーソルを常に表示するように設定する。

左マウスボタン(左クリック)イベントを追加して、次のように実装する。カスタムイベントを呼び出しているが、画面外に該当のカスタムイベントを定義している。

続いてTickイベントを次のように実装する。呼び出すBox Collision ComponentのSet Box ExtentでY軸とZ軸は定数であることに注目。実は今回紹介する実装方法はBox Collision ComponentのExtentのX軸をドラッグ開始地点から終了地点に合わせて伸び縮みさせるだけのものである。

とりあえず実装はここまで。


実装したブループリントをレベルに配置し「Auto Possess Player」を「Player 0」に設定しプレイする。D&Dの開始地点から終了地点までBox Collision Componentが伸びることが確認できるはず。

ただしBox CollisionのExtentのX軸を伸び縮みさせているだけなので、斜めにD&Dしてしまうと奇妙な結果になってしまう。

向きに対応する

斜めにドラッグ&ドロップしてしまうと奇妙な結果になるのは、アクターの回転(向き)を考慮していないため。これまではワールド座標のX軸に向かってD&Dの開始地点から終了地点までの距離を伸ばす実装になっていた。

これを「ローカル座標のX軸方向」に伸ばすように実装する必要がある。これはかなり簡単に実装出来る。

TickイベントのSet Actor Locationノードに続いて次のようなノードを繋げる。


プレイして今度は自由な方向にD&Dしてみる。恐らく求めていたBox Collisionの範囲指定の実装ができたと思う。

大きさに制限をかける

ぷちコンに提出したゲームでは伸ばせる距離に制限をかけている。D&Dの距離をそのまま範囲指定できてしまうとプレイヤーが非常に強くなってしまうのでそのような仕様にした。

伸ばす距離に制限をかけるにはTickイベントのSet Box ExtentノードとSet Actor Locationノードを次のように修正する。赤枠部分が修正箇所。


プレイすると1000cmの長さまでBox Collision Componentが伸ばせることが確認できる。

おまけ

ここまででD&DでBox Collisionを伸ばしたり、向きを変えたりすることができた。主要なメカニズムはこれで完了したので、以降はちょっとしたおまけの内容を書いていく。

チャージに対応する

提出したゲームでは左クリックが押された瞬間から左クリックを離した瞬間までの時間を計測し、その時間の長さに応じて拘束魔法の効果時間を決定している。この「チャージ」を実装していく。

TickイベントのSet Actor Rotationノードの後ろに次のような処理を繋げる。

続いてLeft Mouse ButtonイベントのReleasedピンのClock Tick Gateノードの後ろに経過時間をリセットする処理を加える。

これだけではきちんと動作できているかわからないのでTickイベントのどこかに次のようなデバッグ表示を追加する。


まずは左クリックが押された瞬間からの経過時間を計算するため、デルタ秒を毎フレーム加算する。これによって1秒経過後にはおおよそ1.0、2秒経過後にはおおよそ2.0という数値を取得出来る。この数値をMap Range Clampedノードを使って0.0 ~ 1.0の割合に変換する。画像ではIn Range Bに3.0を指定しているので3秒間かけて0.0~1.0までの数値を出力している。

直接チャージ時間を扱うのではなく割合で扱えるとで色々と便利。後述する「チャージ時間に応じて色を変化する」であったり「チャージ率が最大になったときジャキーンと音を鳴らす」みたいな処理を簡単に追加出来る。チャージ時間を直接扱ってしまうと「やっぱりチャージ時間を5秒にしよう」としたとき色々と計算のし直しが発生してしまう。

色をつける

チャージした時間に応じてDraw Debug Boxの色を変化させる。

チャージ時間の割合はすでに求めているので、実装はかなり簡単。TickイベントのSequenceノードのThen 1ピンの先にあるDraw Debug BoxノードにLerp(Linear Color)ノードを繋げるだけ。見やすさのためにDraw Debug BoxノードのThicknessを20.0ほどにしておく。


今回は色の変化にLerp(Linear Color)を利用したが、Curveアセット(Curve Linear Color)を利用するのもいい。色の補間具合によっては気に入らない色が出てきてしまうこともあるので、そういった場合はCurveアセットで細かに色の変化を定義するといい感じ。

[UE4] 色々な所で使えるCurveアセットの使い方|株式会社ヒストリア