重力を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で無ければならないから。
結果
実行して万有引力を体験してみてください。
この記事が気に入ったらサポートをしてみませんか?