見出し画像

重力を0から組む-万有引力シミュレーション-

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

やりたいこと

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


やっている内容は、「万有引力の計算式でUE5上のアクターに重力を発生させる」という内容です。


準備

2つの赤い球を用意し、互いに重力で引かれるのを観察できるようにします。


新規プロジェクト作成
Blank
スターターコンテンツ オフ


Content下に新規フォルダ作成、以下のようにリネーム
 Blueprints
 Maps
 Materials
 Sky
以降、関連するアクターはこのフォルダに格納する。


Mapsフォルダ内 に 新規レベル を作成
「Main_map」にリネーム

Blueprintsフォルダ内に新規Gamemodeを作成


Main_Gamemode にリネーム


ゲームモードを Main_Gamemode に設定


ベースカラーを赤色にしたマテリアルを作成
M_color とかにリネーム


basecolorピンで右クリック
パラメーターに変換

赤色にして画像の様に繋げる


Engineフォルダ内で Skysphere で検索
SM_Skysphere を skyフォルダにコピペ
※これは好きな空とか宇宙にして貰えば良いです


Main_map を開き、PlayerStart と SM_skysphere をぶち込みます


PlayerStartの位置と角度を画像のようにします
ついでにSM_skysphereも原点に配置しておきましょう。


Sphereを配置
位置を Y=250
マテリアルを M_color に
SimulatePhysics オン
Mass(kg)オン、1.0に
EnableGravity オフ


Active というタグをつけます


Alt+ドラッグ で複製して
位置を Y=-250 に



アクターとその質量を取得

ここではレベル内にあるActiveタグがついているアクターを取得
そのアクターの質量を取得します


Main_Gamemodeを開き
イベントグラフ内に画像のように変数を作成


constantGには1000万を入れておきましょう


下記の様にノードを組みます
① 重い処理なので最初に1度だけ実行します
② Activeタグを持つアクタを探します
⓷ アクタの数だけLoopbodyを実行して、終わったらCompletedを実行
⓸ アクタをActors変数に格納
⑤ アクタのRootコンポーネントにアクセス
⑥ 更にStaticMeshコンポーネントにアクセス
⑦ アクタの質量を取得
⑧ Masses変数に質量を格納
⑨ アクタの数を取得(この場合2)
⑩ Actors#にアクタの数が格納(2が入る)
⑪ 入力した値から マイナス1 した値を入れる
  (この場合1になる、理由は下で説明)

なぜRootからStaticMeshコンポーネントにキャストしなければならないのか?

Rootというのは名前では無く、一番上のコンポーネントという意味ぽい。

恐らく、Actorという一番上の階層があり、そこには位置情報などは無い
その子に何らかのコンポーネントがあり、そこに位置や質量などを持つ
Actor > StaticMesh
という構造

レベル上で選択し、Detailsタブから各コンポーネントが何を保持しているか見る事が出来ます。
(上の階層で下のコンポーネントが持つ物も見える為、上の階層に行くに従って何が減っているか?という見方をせねばならない)

Mass(質量)はStaticMeshコンポーネントの中で見られます。

つまりこのDetailsタブで各コンポーネントが持っている要素を確認して、アクセスしないと質量などは取得できないという事になります。
なので Acotr > StaticMesh のような直での参照はできない

 ※因みにブループリントアクタの場合は左のComponentタブで、各コンポーネントの持つ情報が見られる。


なぜActor#からマイナス1するのか

下で組むプログラムで配列を順番に実行するので、配列の最後の数字が欲しい。だが配列は0から始まる為、マイナス1せねばならないのだ。


これでアクタとその質量を取得できました
今度はそれらに引力を加えましょう。


重力を計算

全アクターが互いにAddforce

まず
全アクタ1つ1つに「自分以外の他のアクタに対して引力を加える」
という処理を組んでいきます
8つアクタがあるとしたら画像のような処理を1~8全員が互いにする

同じMain_Gamemode内に下の様に組みます
① 1fごとに計算しなければならないのでEventTick
② Actor#の数だけ実行、indexで実行中の番号を出力
⓷ 1つのアクタごとに更に他の全アクタに対して実行
⓸ != 入力ピンが同じだったらfalseを返す
⑤ 対象先が自分だった場合に実行しない
⑥ 実行中のアクタのStaticMeshコンポーネントにキャスト
⑦ 実行中のアクタに重力を発生



次に Add force の Force ピンに「万有引力と対象アクターへのベクトル」を入力させます。

万有引力の公式

万有引力の公式を確認しておきましょう

万有引力=定数G ×質量1×質量2÷距離二乗

※「^は乗」つまり「^2」は2乗のこと
※「10^-11」は「1/10^11」、10の11乗分の1のこと

定数Gは 6.67 × 10^-11 なので物凄く小さい
しかしここでは1000万としている
それは、それぐらい大きくしないと目に見えて引き合う事は無いからだ。


万有引力の計算

この万有引力の公式を①②⓷⓸⑤でやっています
① 定数G
② 実行中のアクタの質量と他アクタの質量をGET
⓷ 同じようにそれぞれのアクタをGET
⓸ 定数G×質量M1×質量M2(掛け算割り算は順番を入れ替えても良い)
⑤ ⓸ ÷ r2乗
⑥ 実行中のアクタからその他のアクタへのベクトルを求めてnormalize
⑦ ⑤の万有引力にベクトルを掛けて方向を与えている

ーーーー⑥の解説ーーーー
※座標or位置 とは 原点からのベクトル である。故にvectorと表すのだ

まず実行中アクタと他アクタの位置を取得しています
「A - B」 で B を原点とした A へのベクトルが求められます。
なので 他アクタ ー 実行中アクタ して他アクタへのベクトルを求めます。
そして、そのままだと一瞬で他アクタに引き寄せられてしまうので
Normalizeノードでベクトルの大きさを1にします。
画像で言うと、C が  1になると言う意味。
これで引力をいくら掛けても引力の大きさのままになりますね。

これで完了です。


注意事項


ブループリントアクタだと機能しなくなるので、MeshをRootにD&Dして置き換えてください。
そしてtagは一番上(self)に付ける事


理由

RootノードからStaticMeshコンポーネントにキャストしてる為、
Root、つまり一番上のコンポーネントがStaticMeshで無ければならないから。


結果

実行して万有引力を体験してみてください。





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