※表現上適切で無い点や質問などいただけましたら記事を修正します。
PlayerController を引数に取るノードを使用せずに
Widgetをクリックした点をワールド座標に変換する方法について書きます。
UE4にはじめからある、サードパーソンのプリセットを使用しています。
UE4.24 を使用しています。
厳しいご意見を頂けたら幸いです。
BPやリファレンスの名前がひどすぎるのは許してください。
#動機
- MOBAのミニマップみたいなものを作りたい
- FigureHeadsのようなミニマップを作りたい 公式動画(マップ説明部分)
#動作概要
Widgetの画像サイズでクリック座標を正規化する
正規化したクリック座標をマップ床面(Grandfloor)サイズをかける
マップ床面のローカル座標に変換 (Z座標は適当に持ってくる)
ワールド座標から見たローカル座標の原点位置を足しておわり
レベル
レベルブループリント
やってること
- 0~1で正規化されたクリック座標を -1~1に変換
- -1~1の座標にマップサイズをかけることで、スケール変換
- 画面では左上が原点である座標をワールド空間上の方向に変換
- 画面座標(x,y)とワールド座標(x,y,z)で足りないz座標の値をプレイヤー位置から拝借
- Grandfloorのスケールを無視する。Grandfloorのローカル座標に変換するため前段の(x,y,z)を逆行列に掛ける
- Grandfloorの原点位置(オフセット)を足す
- 結果の確認のために適当なActorを変換後の位置にスポーンさせる
NewBlueprint1 (固定カメラ)
Construction Script
やっていること
- GetActorBoundsにより、マップの床面(Tag: grandfloor)の大きさを取得
- Map Size Halfにマップ床面の大きさを格納
TP_UI (ウィジェットBP)
ここの画面中央のミニマップ部分は[UE4] SceneCapture2Dの平行投影でミニマップを作るを参考にしました。
Image_129に下図に示す Get Mouse Pos 関数をバインドしています。
やっていること
- Imageのサイズでクリックされた箇所の座標(x,y)を0~1で正規化している
- 正規化座標を Normalized Position on Map に格納
# 座標変換ついて
同次変換行列や逆行列を掛けるとなぜローカル座標になるかという点につきましては
ロボティクス 日本機械学会が豊富な図付きで説明されているので分かりやすいと思います。
YTTM WORKさんもわかりやすく説明されています。
https://yttm-work.jp/gmpg/gmpg_index.html
アクタのワールド座標からミニマップ座標への変換
- Actorのワールド座標をカメラのTransformの逆行列につっこむ(上空のNewBlueprint1がカメラ)
- カメラ座標の任意の軸を画面座標のx,y軸と置く
- 座標をGrandfloorのサイズで正規化(0~1)する
- Widgetのミニマップサイズを掛ける(ミニマップの原点は左上に置く0~1の正規化で原点位置を考えなくて良い)