見出し画像

重力を0から組む-惑星の重力で歩きたい-

※素人による記事の為、間違いがある可能性があります
※個人用備忘録ですが、何かご指摘ございましたらコメント頂けたらと思います

やりたいこと

下の動画をやってみた、という記事です


やっている内容は「球体の表面を 球体中心の引力下で 歩く」です。

※現状ではこの手法は「惑星が自転した時にプレイヤーがついていかない」という問題があります。


ステージ作成

ThirdPersonテンプレート
スターターコンテンツ オフ
で新規作成


ステージ類をどけるか、削除


スフィアを原点に配置、スケールを70(お好みでOK)にする


KillZ

ワールド設定のKillZを-20000にしておきます。

KillZ は設定されたZ座標を過ぎるとプレイヤーがDestroyされる設定です。
マリオとか落ちたら死にますよね?あれです。
これをしないと、ある地点より惑星の下に歩けなくなります。
destroyはされませんが、謎です。


プレイヤー作成

浮いて移動するプレイヤーが欲しいので新規で作ります。
コンテンツブラウザ で 右クリック
ブループリントクラス を選択
Pawn を選択
CUM_PlanetWalker にリネーム

Characterじゃない理由
・CharacterMovement は Walkモード は重力がZマイナス方向がデフォルト
・Flyモードは惑星重力に引っ張られ続けるとフワフワ移動し続ける
・FlyだとJumpできない
・スケルタルメッシュの親にルートを作れない(後でつくります)
という Character を使うメリットが無い為 Pawn にします。


カプセルコンポーネント以下をCUM_PlanetWalkerにコピペ

コピー元

DefaultSceneRoot を Capsule で置き換える

コピー先


なぜDefaultSceneRootを置き換えるのか

DefaultSceneRoot はコリジョンを持っておらず
移動系ノードを使った時に、子にコリジョンがあったとしても
Hit が発生しないらしい。

参考元


CUM_PlanetWalkerを球の上に配置
Auto Possess Player を Player0 にしましょう

本来ならGamemodeのPawnを変えますが、これだとGamemodeは変わらず、強制的に指定したプレイヤーになります。
検証だし、これで良いかという事でしょう。


プレイヤーのBP準備

CUM_PlanetWalker(以下CUM)を開きます
FloatingPawnMovementを追加
CanWalkを オン

BP_ThirdPersonで使われているCharacterMovementは
・Walkモードは重力がZマイナス方向がデフォルト
・Flyモードは惑星重力に引っ張られ続けるとフワフワ移動し続ける
というデメリットがある為、FloatingPawnMovement を使用
FloatingPawnMovement は2Dキャラクターなどで使われる移動コンポーネントです。重力はデフォルトでは設定されてないので、浮きながら移動します。


ThirdPerson から Jump以外を CUM へコピペ
※JumpはCharacterクラスじゃないと機能しない、今回はPawnなので使えない(Jumpできるかもしれないけど、今回は諦める)


下記の変数を作成
WorldOrigin vector (これが惑星の中心)
Gravity Float 初期値は -1


カメラをローカル座標基準にする

このままだとカメラは Control Rotation を使用している為
ワールド座標基準となり、プレイヤーが逆さになっていても、カメラだけ天地が最初と同じ角度を維持してしまいます。

まずカメラは Control Rotation を使いたくないので
SpringArm の Use Pawn Controller Rotation をオフにしましょう。


そしたら、Camera Input を黄色枠の部分を新作しましょう
不要なノードは削除してOK
A SpringArmがカメラの回転を決めるので取得
B (Input Y × -2)+ SpringArm Pitch
  そのままだと逆回転な上に遅いのでマイナス2掛けた
C (Input X × 2)+ SpringArm Yaw
  そのままだと遅いので2掛けた
D 親の座標軸基準で回転を設定


移動をカメラ基準にする

ControlRotation=ビューでは無くなったので、Get Controll Rotationは使えませんね。となれば、SpringArm から直接ビューの回転を取得しましょう。
そしてローカルYawの値だけ欲しいです、カメラが俯瞰気味になると進行方向が地面に突き刺さって移動が遅くなるからです。
なので、ローカル回転(Yawだけ取得) > ワールド回転 に変換しましょう。

赤枠だけ新規ノードに置き換えてください。
① get relative rotation SpringArmのローカル回転を取得
            因みにCameraは親と同回転値なので使えません
② Combine Rotators Aでローカル回転、Bでワールド回転を入力
           ローカル回転をワールド回転に変換したい時に使用

プレイヤーに引力を加える

World Origin 変数で設定した位置(原点)に向かってプレイヤーを引っ張る処理 を組んでいきます。

A WorldOriginからプレイヤーへの方向を取得(距離は含まれない)
B Gravityはマイナス値なので、WorldOrigin方向へ反転
  Gravityの大きさで重力も決まる
C Vector分Pawnを引っ張る(動かす)ノード
  Add Movement Imput と違って、方向と量が一緒(Vectorに集約)

Get Unit Directionとは何?

これは From から to への「向き」を vector で返します
イメージとしては From から to の方向に1cmの長さの矢印を作って、
ワールド座標の原点にオフセットしてる感じです。
なので「向き」の情報しか得られないんですね。


プレイヤーを惑星に垂直に立たせる

惑星におけるプレイヤーの前方を求める

まず プレイヤーが進むべき方向 を求めたいです。
それは 単純にプレイヤーの前方 ではありません。
なぜなら惑星の表面を歩く事を想定しているので、進べき方向は常に惑星の中心と垂直でなければなりません。
組んだ内容を図にしてみました、プレイヤーはウンコです。

A WorldOrigin = 原点に設定
B プレイヤーの前方ベクトル
C WorldOrigin から B への方向ベクトル
D C 方向へ WorldOrigin からプレイヤーの距離分伸ばして
  WorldOriginの位置にオフセット
E プレイヤーから D への方向ベクトル

実際組んだのがこちら

やっている事は「原点を中心として、プレイヤーとの距離分回転した前方」を求めた訳ですね。これで惑星表面における前方がわかりました。

※参考元動画では D のオフセットが無かったのを足しました
 これでWorldOrigin変数にどんな値が入っても方向を取得できます。


プレイヤーを回転させる

プレイヤーの惑星における前方を作ったので
あとは垂直と合わせて、回転軸を求められます。

引力の時に組んだノードに赤枠を足して下さい。

Z はプレイヤーからWorldOriginの方向ですよね

Make Rot from XZ
方向 vector を元に、ローカル軸における 位置XZ の向きを決めて回転値を求めます。


前方を求めたノード から Make Rot fromXZ の X に接続


ついでに小さく折りたたんでおきましょう


Forwardにリネーム


進行方向に回転:MeshRootのみver

このままではプレイヤーが同じ方向を見続けるので、進行方向を向くようにします。
自分流verと元動画verを作りました。
違いは「後者はコンポーネントが1つ多いけど計算がシンプル」です。
後者は次の章で書きます。


まず、スケルタルメッシュの親に MeshRoot というコンポーネントを作ります。
 理由
 ・SpringArm まで回転させたくないから
 ・Actor をそのまま回転させるのは難しい(自分は上手く作れなかった)
※注意 Actorは進行方向に向かず、子のMeshRootが回転してるだけになる


プレイヤーにSceneコンポーネントを追加
Sceneコンポーネントとは Null とか Dummy みたいなもの


MeshRootにリネーム、SkeltalMeshだけ子にする

アンダーバーいらないかな・・・


上の章で作った Set Actor Rotation の右に以下の様に繋いでいきます。

A 移動して無くても回転させるとブルブルするので
B Velocityはワールド座標、トップビュー2Dから見た移動値
  なので逆さになると反転してしまうので、下記を使う
  Unrotate Vector Bのローカル座標の移動値を取得
C StartからTargetの方向の回転値を取得
D Current から Target に interp speed の速度で回転
  Current基準のローカル値を返す
E これを入れておけば、可変フレームレートに対応できる
F 今回つくった親ルートっすね
G ローカルYawだけ回転


全体はこんな感じになってればOK


進行方向に回転:MovePointありver


Sceneコンポーネントを2つ追加
MeshRoot
 SkeltalMesh
 MovePoint
となるように親子づけ


SetActorRotationの右に以下のようにノードを組みます。
A Movepointを進行方向に配置

こっちの方が進行方向の回転値を取得しやすいし、良いかもですね・・・



歩行アニメーションを入れる

歩かせましょう。

ABP_Manny を複製
ABP_PlanetWalker にリネーム


ABP_PlanetWalkerを開き
Characterでは無いので、以下の様に繋ぎなおします。

Characterが生きてるか確認してるやつですかね?


Movement Component も無いので、変更
Vector Length もXYだけじゃなくZも移動するので、変更

移動方向と距離を取得している


これも Movement Component は使ってないので AND のピンを外します


ここも同様に外す


後は、アニメーションBPを設定してあげればOK!!!


あとはプレイして惑星を走り回ってください!!!!!

この記事が気に入ったらサポートをしてみませんか?