環境
UE4.25.1
概要
UE4でのロックオンの記事はちらほら見かけるけど、ロックオンカーソルの記事は少ないというのを見て書き始めました。
本記事ではロックオンする対象は1体を想定しています。
マルチロックオンでの運用も可能ですが、Widgetの場合は少し工夫が必要になります。
ロックオンの処理自体は事前に組まれていることを想定しています。
良いサンプルとは言えませんが、とりあえずのロックオンのサンプルとして下記を利用していただいても良いかと思います(このサンプルにはロックオンカーソルのロジックは実装されておりません)
github.com
完成イメージは以下のようになります。
※実装に使用している「LockOnTarget」という変数がありますが
これはActor型の変数でPlayerやLockOn用のComponent等
ロックオン処理を行っているBlueprintから事前にHUD/Widgetに渡されている上での実装になります。
一例としてPlayer側でロックオン処理を組んでいる場合のものを載せておきます。
PlayerRef : プレイヤーBlueprintへの参照
IsLockOn : プレイヤーがロックオン状態か判定するためのフラグ
LockOnTarget : ロックオン対象となるActor(必ず対象がいるとは限らないため、IsValidチェック)
ロックオンカーソル実装(HUD編)
先ずはHUDでの実装についてです。
個人的にはWidgetでの実装をオススメしますが、こちらも紹介しておきます。
下図のようにHUD Blueprint内で処理を組むことでロックオンカーソルを表示できます。
ここで注目すべきは「Project」ノードです。
「Project」ノードでロックオン対象の3次元座標を画面の2次元座標に変換してくれます。
あとはその位置データを元にDraw TextureやDraw Materialでロックオンカーソルを描画するだけです。
注意点として、このノードはHUD内でしか使えず「Event Receive Draw HUD」の中でしか機能しません。
そのため、Tick等で同じノードを組んだ場合には動作しません。
ロックオンカーソル実装(Widget編)
続いてWidgetでの実装です。
Widget内のDesignerでは図のようにCanvasPanelとImageだけのものを用意します。
この時にLockOnCursorのVisibilityを「Hidden」か「Collapsed」にしておきます。
表示されてほしいのはロックオン中のみですので、デフォルトでは非表示でよいです。
あとは図のようにBlueprintを組めば完成です。
ロックオン対象が存在する時は表示して座標を更新し、いない時は非表示に切り替えています。
HUDではProjectを使用して2次元座標に変換していましたが
ProjectはHUD専用ですので、こちらではPlayerControllerの「Project World to Screen」を使用します。
この辺りの処理は何度か使うようであれば、関数ライブラリ等にまとめてしまってもよいかもしれませんね。
ロックオン処理の実装にもよりますが、開始/終了判定が取れる場合は以下のようによりシンプルにまとまると思います。
まとめ
個人的にはWidgetでの実装をオススメしますが
とHUD編で書いたのですが、この理由についていくつか解説します
1. ロックオン開始時のアニメーションを追加できる
ロックオンした時のカーソルの回転や拡縮や色替えなど各種アニメーションをWidgetで組んで実装することができます。
HUDでも出来るかもしれませんが、結構な手間なので避けたいところです。
ロックオン開始時ではなく、常時回転などを行いたい場合は以下のようにMaterialで組めばよいです
papersloth.hatenablog.com
2. 画面サイズの変更に強い
HUD版の現実装では画面解像度等を変えた時にロックオンカーソルも大きさが変わってしまいます。
これでちょうど良いサイズになってくれると良いのですが、少し処理を加えて調整してやる必要があります。
Widget版ではViewportScaleを考慮して計算しているため、表示 / 非表示の切り替えくらいで特に何も手を加える必要がない想定です。
HUDでの利点もないわけではないです。
マルチロックオンを行いたい場合は比較的処理が楽です。
Draw Texture/Materialが同時にロックオンした数と同じだけ描画されることにだけだからです。
例で渡したLockOnTargetを配列にしてループを回すだけで済みます。
同じことをWidget版でやりたい場合は少し手間です。
図のようにLockOnCursorだけのWidgetを作成しておき
ロックオン開始時にメインのWidgetのPanelにAdd Childして終了時にRemove Childする等でしょうか。
ロックオンカーソルについては以上になります。