【Unreal Engine5】初めてのゲーム開発 <第18回>カメラ自動追尾とカメラ基準のラジコン移動

今回は「カメラの追尾をどうするか?」という部分から。

《今回の記事後の実行テスト》

リアルタイムで方向転換する方式ではなく、パワーを溜めてボールを弾く方式なので、レースゲームとは多少画面の挙動は異なります。
遠くからの固定カメラより臨場感のある(というか見慣れた)カメラワークになったと思います。

右下のメーター
数字:現在のスピード
円ゲージ:発射用のパワーゲージ

目次

キャラの移動方法(ラジコンタイプ/ワールド座標タイプ)

かなり重要で、どちらが向いているゲームなのか考える必要がある。

ラジコンタイプ

キャラの向いてる方向から算定し、前後左右上下で移動する方式
現在のFPS/TPSゲーム、そしてレースゲームの主流移動方式であり、プレイヤ―主体でワールドが回転するイメージ。
【プレイヤー = 操作するPawn】という感覚に近く臨場感や没入感を与える
WASD移動タイプの場合はプレイヤーの意思以外でカメラの方向が変わると操作感が悪くなる
基本的にはカメラは独立してマウスか右スティックに割り当てることが多い。

実際の画面でみてみると

プレイヤーへの距離400

プレイヤーへの距離200やや右

カメラ移動の制約は少なく、特にマウスとの親和性が高い。

ワールド座標タイプ

ワールドの東西南北上下で移動する方式
【プレイヤー = 神視点】で指示するという感覚に近い。
カメラ視点は固定もしくは平行移動のみ、臨場感を与えるには不向き
緻密な移動向きで、周囲の状況で操作判断させるゲームに向いている
レトロゲーム、パズルゲーム、ストラテジーゲームなど指示を与えるゲーム向け。

実際の画面でみてみると

プレイヤーへの距離1000

プレイヤーへの距離2000

(基本的に)ワールドの東西南北を変更できないので、基本的にカメラの移動に制約が課される。

どちらを採用するか?

特徴をまとめる前はワールド座標タイプ一択だと思っていたのですが、メリット・デメリットを考えると悩ましい。
3Dタイプのゲームの強みは臨場感だと思っているので、よほど大きな理由がない限り後者は選びづらい。
後者はカメラ移動も難しいので、2Dゲームのプレイフィールに近い。

実は、ワールド座標タイプでいろいろ動作テストなどを進めていたのですが、並べてみるとどうみてもラジコンタイプの方が見栄えがいいんですよね…

ラジコンタイプ

前回記事のもの。
移動などは未実装ですが比較用として。

ワールド座標タイプ

おはじき?ゴルフ?のようにボールを転がしていく。

ゲーム性とかはこれからですが、既に見た目で負けてる感
移動方法とかカメラ位置とか考えてはみたけど、没ですねぇ。

未だ目的のゲームの像が出来てるわけではないが、ラジコンタイプを軸に考えていきたいと思います。
ただし、マウスでのカメラ移動だと今回は問題があるので、カメラは追従式(レースゲーム方式)。

プレイヤーの向き=カメラの向きにするには?

プレイヤーの向き=カメラの向きというこの設定はWASD移動とは相性は最悪です。
これはカメラの向きが変わることで、WASDの方向が動的にズレていくことが原因
単純に右に行きたいのに、その場でクルクルと回転する事態になります。

最悪とはいいましたが、あくまでカメラと自動的に連動させる場合の話。
FPS、レースゲームでは基本的にWASDは向きの変更だけであり、移動自体は前後のみですし、TPSではカメラの移動は独立した操作(マウスや右スティック)なので問題なし。

今回は連続してWASDで移動するわけではなく、決めた方向に対してボール(自身)を弾く方式なのでレースゲームに近い。



《参考にさせてもらった記事》
【UE4・UE5】〈Tips〉TPSキャラクターの向いている方向とカメラとの角度の取得

Delta (Rotator)のうち、Yawの変動のみに着目して図示すると以下のようになりました。

+-に関してはもしかしたらワールドの生成で変化する可能性がありますので同じ結果にならないかもしれません。


今回のケースでは、キャラクターが右を向いたら、カメラのYawを-90したらカメラの向きも右向きになるということ。

BP_PlayerBall(Player Pawn)

※もっとスマートな方法はあるはず(笑)


進行方向とカメラの方向のズレはDelta (Rotator)ノードを使用して算定。
右回り・左回りのどちらかを判定して、Add Controller Yaw Inputで少しずつ回転。
これをEventTick(毎フレーム)行うことでカメラの向きをXY平面(Yaw)のみ、自身(ボール)の移動方向に合わせます。

以下の処理を毎フレーム行っています
① カメラの現在の向きを取得
② 自身の移動方向を取得(前フレームの自分の位置から現在の位置をFind Look at Lotation)
③ ①と②のズレを取得
④ Z軸(Yaw)のズレが5以上あった場合、ズレの方向にカメラを移動

⑤ 現在の自分の位置を前フレームの位置として変数登録

Get Camera Rotation
Get Actor Rotation
カメラとアクタ(自身)の回転を取得。
カメラのTargetはGet Player Camera Managerで取得したもの。
Delta (Rotator)AとBのRotationのズレをrotate(Roll/Pitch/Yaw)で算定。
今回は左右のズレ(Yaw)のみを使用すためにピンを分割して使用。
BranchAとBのYawのズレが+-5以上であった場合、カメラの向きを変える
Add Controller Yaw Input+方向(左側)であれば-1、-方向(右側)であれば1だけcameraの方向を変更
RotationZ(回転距離)はデフォルト値(1)を使用

Cameraの向きに関してはEventTickで滑らかに追従させます。
Rotation Z (Yaw)はローカルの変数(設定値1)で1フレームに1ずつ、Cameraの向きをキャラの向きに合わせていく処理にしています。

これでキャラクターの移動方向にカメラが追従するはずです。

重要なのでもう一度いいますが、WASD等の継続的にキー入力する移動方式とは相性が悪いのでWASD移動との併用はオススメしません。
+-5度の許容範囲を設けているのは、これがないとカメラがガクガクしてしまうため。

Get Physics Linear Velocityから直接Delta (Rotator)のようなノードに持って行ければ「方向=前座標から今の座標の向き」等という冗長なコーディングにならずに済むはずですが、わからなかったので力業でのコーディングになっています。

《カメラテスト》
移動動作は次の項目で行っているのですが、実際にどのような動きになるかの参考として

一般的にレースゲームではカメラは自動追尾ですが、近い挙動になってきたのではないでしょうか。

6秒あたりの180度ターンでカメラがガクガクしてるのは、おそらく左回り・右周りの判定が上手くできていないバグ。
15秒あたりの180度ターンのように上手くいくこともあるようです。

今はAdd Impulse(運動エネルギー追加)の代わりにSet Physics Linear Velocity(運動エネルギー設定)で挙動チェックしている段階なので、最終的に気になるようであれば手直しを考えますがどちらかというとバック(下キー)自体を抑制する方が楽ではあります。

WASDで進行方向に進むようにする

今回はテスト結果が分かりやすいようにAddImplseによる速度加速ではなく、Set Physics Linear Velocityによる速度設定を使用しています。

現在の仕様

ワールドマップの軸に合わせた移動

W X軸(+)方向
A Y軸(-)方向
S X軸(-)方向
D Y軸(+)方向

あるべき仕様

プレイヤーの向きに合わせた移動

W 進行方向(前)
A 進行方向(左)
S 進行方向(右)
D 進行方向(後ろ)※実装するのであれば

一般的にプレイヤーにとってはカメラの向き=コントローラーの前後左右の基準
なので、せっかく前章で追尾してくれるようにしたカメラの向きを使っていきます

WBP_Gauge2(User Widget)

今回のプレイヤー(BP_PlayerBall)の挙動はゲージ表示(WBP_Gauge2)と連動しているので、記述はWBP_Gauge2で行うことにします。

Event Pre Construct

最初にボール(BP_PlayerBall)を変数化して取得。
もしプレイヤーのリスポーンが発生する場合、新たに設定する必要がある(今回は考慮していない)。

Enhanced Action Events IA_Move

※以前プレイヤーPawn(BP_PlayerBall)に記載したものは削除

WASDが押された時に押されたキーを記憶する処理(同時押し許容)。
AD同時だとD優先、WS同時だとS優先(仕様)。

各キーが押された時に、X軸への加速(BoostX)、Y軸への移動(BoostY)へ-1,0,1のいずれかをセットします。
XY平面上でどちらの方向のキーが押されたかの判断に使用。
BoostX,BoostYは次にWASDが押されるまで(キーを離しても)値を保持。

設定値表

WS押さない
ABoost X:1
Boost Y:-1
Boost X:-1
Boost Y:-1
Boost X:0
Boost Y:-1
DBoost X:1
Boost Y:1
Boost X:-1
Boost Y: 1
Boost X:0
Boost Y:1
押さないBoost X:1
Boost Y:0
Boost X:-1
Boost Y: 0
その他の変数設定

・BoostCT変数
ブースト射出の連続使用抑制(現在は0しか設定されないので連続使用可)。
将来的に使用することを考えて。

・Power変数
現在の射出パワー(%)を示す。
WASDを押してる間に0.02(2%)ずつ加算され、1.5(150%)までいくとリセットされる。

EventTick

前半

前回(第17回)で行った処理とほぼ同様。
ボールインスタンスを取得する部分を初期設定(Event Pre Construct)に移動しただけ。

後半

Power変数(射出パワー)とBoostCTを毎フレーム0.01ずつ減少。
1秒間に0.6持続的に減少することになる。
このあたりは増加値と合わせて要調整。

最後に現在のPowerを引数にSet Percent(画面表示)へ。
SetPersentに関しては前回(第17回)のものを流用したので省略。

Enhanced Action Events IA_Jump(スペースバーを押した時の処理)

※以前プレイヤーPawn(BP_PlayerBall)に記載したものは削除

Power(射出パワー%)に応じて運動エネルギーをBP_PlayerBall(Player Pawn)に与える。
もはやJumpではないのだが、キー入力の関係をそのまま流用してるので…

最初にBoostCTによる抑制時の処理(現在未使用)。
右上部でBoostDrection(入力加速方向とパワー)を設定
下部でRotate Vectorでカメラ方向へずらしてから、Set Physics Linear Velocityでプレイヤーの運動エネルギーを設定。

おそらく分かりづらいのが左下のカメラの方向による調整で、ここでカメラの向きに応じた前後左右への運動エネルギーへ変換しています。

Get Camera RotationのYaw(Z軸に対する回転)をPrint Stringで表示してみると

カメラを右周りに回転させます。
0付近

90付近

-180/180付近

-90付近

こんな感じで、基準方向に対する現在のカメラの向きを取得できます。
今回はYaw以外の回転軸は無視して左右方向のみ、BoostDirectionの方向をずらしています

これでカメラ方向を軸として、WASDで前後左右の動きになるはず。

押してる方向キーを表示

※必ずしも必要ではない

前回やったMaterial(User Interface)の復習に、押した方向の矢印キーの色が変わるようなwidgetを作ってみましょう。
ダンジョンRPGとかであるやつ。
最終的は消すかもしれませんが、テストで触ってる時はあった方が分かりやすいので。

矢印の画像はwindowsのイラストソフトで作成したものを透過処理(png)したのを用意しました。
デフォルト用で用意するのは白アイコン+透過がいいと思います。
フリーの透過済イラスト素材などを入手した方が高画質の物が使えるのでオススメ。

配置時、アンカーは画面中央にしてください。


ウィジェットにimgで追加。
角度を変える際は、レンダートランスフォームのAngleを変更。

W:Action Value Y=1
A: Action Value X=-1
D:Action Value X=1

なので

Make StateColor色を作成
Set Brush Tint ColorTargetのBrush Tint Colorを変更

ゴチャゴチャしてるのです(ごめんなさい)が、要は3種類のイメージ(前/右/左)の色を緑にしたり白に戻したりしてるだけ。
①トリガー時、WADの押されてる矢印の色を緑に
②完了時、WADの矢印の色を全て白に

《実行テスト》

加速度の設定処理 ⇒ 加速度の加算処理

テストでは便利だったのでSet Physics Linear Velocityを使ってましたが、Add Impulseに戻します。

修正箇所は、Enhanced Action Events IA_Moveの最後に呼ぶノードを変えるだけ

ここまでやった後の実行テストが、冒頭の動画。

Add Impulseにしたことで、運動エネルギーがリセットされないので速度がどんどん上がっていくのが分かります。
そして左右に運動エネルギーを与えた際にも前方への運動エネルギーがあるので90度コースが変わるみたいな物理法則無視もありません。

レースゲーム等で使われる挙動に近くなったのではないでしょうか。
パズルのような精密な挙動が必要なのであればSet Physics Linear Velocityに戻すことも考えるので一応隣に置いておきます。

最後に

第17回と今回は、ボールを弾いて動かす挙動に焦点を当ててみました。
この2回で作ったボールの挙動は個人的には満足。

基礎的な動きは出来た(気がする)ので、そろそろゲームの仕組みとかを考えねば。
色々忙しくなりそうなので更新ペースはかなり落ちる予定です。

この1か月UE5の記事ばっかりだったので、そろそろメインの記事も…



コメント

コメントする

目次