UE5 プレイヤーを操作してタイル間を移動

# 概要

:::note
**追記**： 色々バグってたので修正済。同時押し等の問題も解決
:::

プレイヤーを操作してタイル間を移動してみる。

入力は **Enhanced Input**、移動は **Move Component To** ノードで行う。

![cm40_3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/d69ba045-0548-debf-4dc0-bf57f4595948.gif)

前回

https://qiita.com/tukanpo/items/704ea3a179054a948ca0

今回の内容のプロジェクト一式

https://github.com/tukanpo/CM40/tree/v4

## 環境

UE 5.5.1

# Enhanced Input

移動入力する為のアセットを作成する。

コンテンツブラウザで右クリック > 入力 > 入力アクション で **IA_Move** を追加。

![2025-01-19_16h47_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/3e9af0d0-5a79-4cc5-367a-be7d6597a6a5.png)

## IA_Move

移動用の **入力アクション** を追加

ここで定義するのは、このアクションに対してどんなパラメータが必要となるのか？
前後左右への移動は2Dの軸方向 (x, y) で表すことが出来るので、今回は **Vector2D** を指定する。

![2025-01-19_18h21_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/b1be8e0e-15fc-cd92-f86e-692e3899f995.png)

ValueType : Axis2D (Vector 2D)

## IMC_InGame

**入力マッピングコンテキスト** を追加

![2025-01-19_16h48_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/174029bd-af0a-c94d-c360-6461563cba64.png)

とりあえずキーボードの WASD に移動入力を割り当ててみる。

[公式ドキュメント](https://dev.epicgames.com/documentation/ja-jp/unreal-engine/enhanced-input-in-unreal-engine#%E6%96%B9%E5%90%91%E5%85%A5%E5%8A%9B)から引用した表がこちら。多分これで良い？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/207874cb-bde7-a373-c358-de255c2e9959.png)

ぱっと見よく分からないのが、入力モディファイアの部分。
**Swizzle** ってなんや… と思って ChatGPT に聞いてみたら以下のような意味らしい。

> 「Swizzle」は、プログラミングやコンピュータグラフィックスの分野で、データの並び順を変更する操作を指します。特に、ベクトルや軸の順序を再配置することを意味します。

**IA_Move** に対して W / A / S / D の４種を設定する。

- 各キー入力は **0（押していない）または 1（押している）の値のみ** を返す
- 各キー入力は、まず **単純な X 軸の値（0 または 1）として解釈** される
- 各キーの目的に応じて、入力値を入力モディファイアで加工する

  - W キーは正の Y 方向なので X と Y を入れ替える (Swizzle)
  - A キーは負の X 方向なので負の値に変換する (Negate)
  - S キーは負の Y 方向なので X と Y を入れ替え、負の値に変換する (Negate Swizzle)
  - D キーは正の X 方向なので加工しない

そしてキーは１回押すごとに実行としたいので Triggers に **押される** (Pressed) を追加。

下記の通り

![2025-01-21_14h43_52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/2e12178e-0df9-afb8-fba1-b5ef44955dff.png)

# BP_PlayerController

## プレイヤーに対して入力マッピングコンテキストを適用する

※ **フルブループリントエディタを開く** を押してグラフを編集できるようにしておく。

**GetEnhancedInputLocalPlayerSubsystem** を追加

![2025-01-20_01h21_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/44ca2b2e-51b3-9eac-f7c6-e76eb1d672fd.png)

ピンを伸ばして **Add Mapping Context** 追加

![2025-01-20_01h22_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/5375da15-6822-c7b4-08a1-614a7a8aa22c.png)

BeginPlay と繋げる

![2025-01-20_01h22_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/41225426-965a-4988-06e2-bb5a9fd47d96.png)

IMC_InGame を指定。

![2025-01-20_01h28_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/b6833a1c-9e07-f548-231a-2d255317e960.png)

おためしで IA_Move が呼ばれたら画面にログを出力してみる。
グラフに IA_Move を追加して Print String。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/13694bdf-3a1c-1a87-8e18-30d406a4efba.png)

WASD の各ログ結果
```
LogBlueprintUserMessages: [BP_PlayerController_C_0] X=0.000 Y=1.000
LogBlueprintUserMessages: [BP_PlayerController_C_0] X=-1.000 Y=-0.000
LogBlueprintUserMessages: [BP_PlayerController_C_0] X=-0.000 Y=-1.000
LogBlueprintUserMessages: [BP_PlayerController_C_0] X=1.000 Y=0.000
```
# BP_Player

プレイヤーの移動は一番簡単そうな **Move Component To** ノードを使う。

## カスタムイベント MoveToTile を追加

プレイヤーのタイル間移動処理を作成する。

イベントグラフで右クリックしてカスタムイベントを追加する。
名前は **MoveToTile**

![2025-01-21_13h19_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/3c6704c1-96ff-d98c-de16-b5682b7fa339.png)

### インプット

- TargetTile (BP_BoardTile)
- Duration (float)

![2025-01-21_13h27_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/337a03ff-b686-8151-011d-92d4b47cd8db.png)

## 変数追加

bMoving (boolean)

### ノード

![2025-01-25_01h02_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/b2b42a42-4cea-de11-fb9a-e91d3fc15471.png)
※ 後述する進行方向への回転処理も含めている

**Move Component To** は非同期で動作する、**Latent** という種別のノードとなる。
Latent ノードはイベントグラフでのみ利用可能で、関数内では利用不可。

![2025-01-21_14h36_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/343f3b4c-7208-c2da-bd48-9908529ffc80.png)

# BP_PlayerController

## IA_Move イベントが来た時の処理を実装する。

具体的には、

- 入力値とプレイヤーのグリッド座標を足して、次のグリッド座標を求める
- グリッド座標をキーにタイルのコンテナから移動先タイルを取得（無ければエラー表示）
- 先ほど作ったカスタムイベントの MoveToTile を呼ぶ

多分もっと綺麗にまとめられるのだろうけど、ノードをあまり知らないのでとりあえず動けばヨシで。

![2025-01-21_14h53_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/0c5b00fb-f64f-efe8-4315-071bd766c006.png)

下記はノードをダブルクリックで追加できる Reroute ノード。整理用
![2025-01-21_14h53_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/2e53c86d-9b7b-89bd-2220-195a55a2f6a9.png)

一応これで WASD 入力によるタイル間の移動が可能になる。

…が、このままではまだ色々問題があるのでそれぞれ対応する。

![2025-01-21_15h14_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/f34460fd-d7d7-c6bc-0992-2e97c2a13823.png)

# 残りの問題を修正

## 移動方向が X, Y で逆

※ 前回のプロジェクトから進めた場合のみの問題

前回までに作成したコードではグリッド座標の X, Y を UE の座標軸へそのまま配置してしまっているのでタイルの X, Y が入れ替わり意図しない方向に動いてしまう。

なのでタイルの生成位置はグリッド座標と同じく X が横で Y が縦(奥) となるように生成時の座標計算のノードを変更する。

BP_GameBoard の **CalcTileLocation** 関数を修正。

![2025-01-21_15h04_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/8ba6efe3-a4c4-2620-7f91-78f7561d7282.png)

## 移動時に進行方向へ向かせたい

アニメーションではなく瞬時に進行方向へ回転させる。

## 関数追加
BP_Player に **RoateteToTile** 関数を作成する。

#### インプット
TargetTile (BP_BoardTile)

#### アウトプット
NewRoatation (Vector)

![2025-01-23_10h36_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/939077be-6354-ef3a-cf65-7c6b0bfcf9f3.png)

### イベントグラフを修正

![2025-01-23_10h42_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/a82bc733-09d2-7334-e8c5-872be912188a.png)

## スプリングアームの設定変更

カメラが回転に追従しないよう、SpringArm の下記チェックを全て外す。

![2025-01-23_13h46_38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/57dd739d-cf3c-5de5-2a75-b4a4d32175c5.png)

## 同時押しによる斜め移動を防止

BP_PlayerController の IA_Move の最初に判定する

![2025-01-25_01h26_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18334/c1a1ad8f-4e74-3126-b0a0-d5129604e0d8.png)

おわり