【Unity道場】物理シミュレーション完全マスター

2.9K Views

January 24, 18

スライド概要

2018/1/25に開催されたUnity道場 物理シミュレーション完全マスター の講演スライドです。
講師:安原 祐二( ユニティ・テクノロジーズ・ジャパン合同会社 )

ゲームのみならず様々なアプリケーションにおいて、物理挙動の導入は品質の向上や開発の効率化につながります。Unityに搭載されている物理シミュレーションはたいへん優れたもので、その原理を理解することでより一層表現力が高まるでしょう。この講演では、物理の初歩を丁寧に解説しつつ、プロの現場で応用されるテクニックについてお話しします。

こんな人にオススメ
・UnityでRigidbodyを使用したことのあるプログラマ
・物理シミュレーションの概観を知りたい方

得られる知見
・コンピュータにおける物理シミュレーションの原理
・物理シミュレーションを扱う上での注意点
・物理シミュレーションの具体的な応用例

関連動画:
[Unity道場 札幌スペシャル]プロが教える脱初心者スクリプト術!
https://youtu.be/FqjM9oujyNE

Unityのイベント資料はこちらから:
https://www.slideshare.net/UnityTechnologiesJapan/clipboards

profile-image

リアルタイム3Dコンテンツを制作・運用するための世界的にリードするプラットフォームである「Unity」の日本国内における販売、サポート、コミュニティ活動、研究開発、教育支援を行っています。ゲーム開発者からアーティスト、建築家、自動車デザイナー、映画製作者など、さまざまなクリエイターがUnityを使い想像力を発揮しています。

シェア

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

෺ཧγϛϡϨʔγϣϯ ‫׬‬શϚελʔ 東京版 フィールド・エンジニア 安原 祐二

2.

白く塗装した2つの球。 片方は純金製、 片方は純銀製。 素材を特定する方法は? ・色、形、大きさは同じ ・質量、重心も同じ ・純金製の球は中空(上図) ・純銀製の球は稠密(下図)

3.

積分 完全マスター

4.

3個 4列 3×4=12 3個×4列=12個

5.

3m 4m 3×4=12 2 3m×4m=12m

6.

長さと長さを掛けると 3m 面積? 4m 3×4=12 2 3m×4m=12m

7.

3m 3個 4m 4列 12個 ぜんぜん違う話! 12m2

8.

長さと長さを掛けると 3m 面積? 4m 積分の神秘は 3×4=12 2 3m×4m=12m これと同じ

9.

3 極小の長さぶんを

10.

3 範囲ぶん足す

11.

3m 4m 12m2 単位が変わる

12.

y x x x 極小長さ: 方向の微小区間 dx(デルタ )という

13.

y x 面積を出す x で積分する

14.

長さmを長さmで積分→面積m2

15.

長さmを長さmで積分→面積m2 2 3 面積m を長さmで積分→体積m 積分すると必ず単位が変化する

16.

Z 積分の計算には を使う (いんてぐらる) 計算は呪文のようなもの 理解そのものとは無関係

17.

例:球の体積(部分) 呪文 V y = = S = r t = x = 理解 Z Z t Sdx r t ⇡(r2 x2 )dx r 3 x ⇡[r2 x ]t r 3 3 t ⇡{r2 t ( r2 r 3 t3 2 3 2 ( + r t + r )⇡ 3 3 円の面積を重ねる r3 )} 3

18.

〜今回のおはなし〜 最小実装 外力 接触 力積 慣性テンソル

19.

物理シミュレーションの 最小実装

20.

2 加速度m/s を時間tで積分→速度m/s

21.

2 加速度m/s を時間tで積分→速度m/s velocity += acceleration * dt;

22.

2 加速度m/s を時間tで積分→速度m/s velocity += acceleration * dt; 速度m/sを時間tで積分→位置m

23.

2 加速度m/s を時間tで積分→速度m/s velocity += acceleration * dt; 速度m/sを時間tで積分→位置m position += velocity * dt; これが物理シミュ

24.

動画 最小実装はこれだ!

25.
[beta]
public class MyRigidbody : MonoBehaviour {
public Vector3 acceleration;
public Vector3 velocity;
public Vector3 position;
const float dt = 1f/60f;
public void AddForce(Vector3 force) {
acceleration += force;
}
void FixedUpdate() {
velocity += acceleration * dt;
position += velocity * dt;
if (position.y < 0.5f) {
velocity = -velocity;
}
transform.position = position;
acceleration = Vector3.zero;
}
}

26.

Unityの物理更新と FixedUpdate

27.

60fpsのゲームは dt 1秒 60回 1秒に60回画面を更新している

28.

60fpsのゲームは dt 1秒 60回 1秒に60回画面を更新している

29.

1/60秒 処理 余裕 余裕期間は待機

30.

余裕 1/60秒

31.

余裕 1/60秒

32.

余裕 1/60秒

33.

余裕 1/60秒

34.

超過 1/60秒

35.

待機 1/60秒

36.

責任重大 1/60秒

37.

1/60秒 通常更新 物理計算 FixedUpdate Update

38.

1/60秒 通常更新 物理計算 FixedUpdate Update 物理更新

39.

物理計算 FixedUpdate 物理計算 FixedUpdate 物理更新 責任重大 フレーム 物理更新 Update 物理更新は複数回実行される

40.

責任重大 フレーム 物理計算 FixedUpdate 物理計算 FixedUpdate Time.fixedDeltaTime Update Time.deltaTime ※TimeManagerの設定で事情は変化 固定 Updateは 変動 dtが変動

41.

物理計算 FixedUpdate 物理計算 FixedUpdate OnCollisionEnter OnCollisionExit OnTriggerEnter 物理更新 OnCollision*は から

42.

外力

43.

運動方程式 F = ma F :力 m:質量 a :加速度

44.

運動方程式 F = ma F :力 m:質量 a :加速度 物理シミュレーションは 位置を知りたい F a= m 質量は固定なので 加速度は力

45.

加速度があれば位置を出せる 2 加速度m/s を時間tで積分→速度m/s velocity += acceleration * dt; 速度m/sを時間tで積分→位置m position += velocity * dt; これが物理シミュ

46.

力ベクトルは足せる

47.

物理計算 FixedUpdate 物理更新

48.

物理更新 物理計算 FixedUpdate

49.

重力 物理更新 物理計算 様々な力を 反発力 摩擦力 FixedUpdate +) AddForce トータル外力 足す

50.

AddForceは足すだけ void FixedUpdate() { Vector3 f = new Vector3(0f, -9.81f, 0f); // 重力 f += new Vector3(1f, 0f, 0f); // 風の影響 f += new Vector3(0f, 1f, 0f); // 浮力 rigidbody.AddForce(f); } こんなふうにあらかじめ足しても良い AddForceをそれぞれ呼ぶのと同じ

51.

外力の応用 浮力

52.

浮力とは 物体が押しのけた水の重さ 潜っている部分の体積 潜っている部分の重心 かなりたいへん

53.

浮力の計算はたいへん 球で代用する 単純な式で出せる! 向きを考慮しなくていい 波の対応も容易

54.

動画 浮力っぽい

55.

浮力の計算はたいへん y 球で代用する S r t x t3 2 V =( + r2 t + r3 )⇡ 3 3 単純な式で出せる! 向きを考慮しなくていい 波の対応も容易

56.

力積

57.

運動方程式 F = ma F :力 m:質量 a :加速度 加速度は 微小期間の速度変化 dv a= dt

58.

加速度は 微小期間の速度変化 F = ma dv a= dt dv F = m dt これも運動方程式

59.

加速度は 微小期間の速度変化 力積 Fdt= mdv 運動量(速度)の変化 dv F = m dt

60.

力積も運動量も F = ma の変形に過ぎない 加速度は 微小期間の速度変化 力積 Fdt= mdv 運動量(速度)の変化 dv F = m dt

61.

「力積は運動量を変化させる」 Fdt= mdv dt期間に発生した力の合算を 速度変化に適用する術

62.

「力積は運動量を変化させる」 Fdt= mdv dt期間に発生した力の合算を 速度変化に適用する術 瞬間的に発生する力に使う

63.

爆発で吹っ飛ばしたい 爆発力が存在する期間 AddForce を呼べばいい が、爆発は一瞬 dtが大き過ぎて一瞬を作れない

64.

ForceMode.Impulse rigidbody.AddForce(force, ForceMode.Impulse);

65.

ForceMode.Impulse rigidbody.AddForce(force, ForceMode.Impulse); 内部的には速度の直接変更 (Fdt= mdv の右辺) 質量は考慮するが は考慮しない dt

66.

ForceMode.Impulse rigidbody.AddForce(force, ForceMode.Impulse); 内部的には速度の直接変更 (Fdt= mdv の右辺) 質量は考慮するが は考慮しない dt dt に依存しない速度変化になる OnCollisionEnterなどの瞬間的な力

67.

誤 dtを変えると動作が変わってしまう if (hit) { rb.AddForce(force); } 正 瞬間的な外力には力積を使用する if (hit) { rb.AddForce(force, ForceMode.Impulse); }

68.

Drag

69.

Dragとは 速度に比例した抵抗力 例:空気抵抗

70.

v 指定終端速度 を得るための外力F v k m F = 1 kdt m:質量 k :Drag 参 考 [Unity]RigidbodyのDragから終端速度を得る https://qiita.com/yuji_yasuhara/items/1f438f0f27f5ef854a73

71.

考 参 〜実践的な物理入門〜 [Unity道場 札幌スペシャル] プロが教える脱初心者スクリプト術! https://www.youtube.com/watch?v=FqjM9oujyNE

72.

物理シミュレーションの ウソ

73.

仮に物理シミュが完璧なら こんなに設定は必要ない

74.

なにがウソなのか? dt が大きすぎる あらゆる問題の根源

75.

なにがウソなのか? dt が大きすぎる あらゆる問題の根源 あらゆる工夫 物理シミュレーションの品質

76.

実現困難な例 Wikipedia「Newton’s cradle」より https://en.wikipedia.org/wiki/Newton%27s_cradle

77.

接触

78.

接触していない 移動

79.

接触!(図形的に算出) 接触=必ず潜り込みが発生

80.

潜り込みを直す 位置と角度を調整 Solve(ソルブ) と呼ばれる処理

81.

接触は 物理シミュレーションの 最大の難関 多くの進化や工夫は ここに集約される

82.

下にも物体があったら 調整したせいで潜り込む!

83.

何度も調整 負荷大 求める完全さは アプリの特徴次第

84.

慣性テンソル

86.

「質量m」 dvv 外力 F = m dt v:速度 質量は「動かしにくさ」

87.

移動における「質量m」 dvv 外力 F = m dt v:速度 回転ににおける「慣性テンソル I 」 ! d! トルク T = I dt !:角速度 慣性テンソルは「回しにくさ」

88.

動画 慣性テンソルを可視化

89.

回しにくい 回しにくい 回しやすい

90.

ここからは武装が必要 外積 テンソル 行列 トルク

91.

外積 〜ベクトルの立体関係〜 A 外積 A×B B どちらのベクトルにも 垂直なベクトル

92.

行列 〜ベクトルに掛けるもの〜 A = PB BにPを掛けたらA AもBもひとつの値(スカラー)なら大きさしか変えない が、ベクトルの場合は大きさも方向も変えるのでPは行列 0 1 Ax @ Ay A Az = 0 P00 @ P10 P20 P01 P11 P21 10 1 P02 Bx P12 [email protected] By A P22 Bz

93.

テンソル 〜単なる呼びかた〜 スカラー 0階テンソル ベクトル 1階テンソル 行列 2階テンソル 今回扱うのは2階テンソル

94.

トルク〜回転力の記述〜 回転には必ず回転軸がある 回転させる力をトルクと呼ぶ トルク(と角速度)は 軸ベクトルで表現

95.

再掲 加速度があれば位置を出せる 2 加速度m/s を時間tで積分→速度m/s velocity += acceleration * dt; 速度m/sを時間tで積分→位置m position += velocity * dt; これが物理シミュ

96.

加速度があれば位置を出せる 加速度があれば(速度を出せるから)位置を出せる

97.

加速度があれば位置を出せる 加速度があれば(速度を出せるから)位置を出せる トルクがあれば姿勢を出せる

98.

加速度があれば位置を出せる 加速度があれば(速度を出せるから)位置を出せる トルクがあれば姿勢を出せる トルクから角速度を出せば姿勢を出せる

99.

加速度があれば位置を出せる 加速度があれば(速度を出せるから)位置を出せる トルクがあれば姿勢を出せる トルクから角速度を出せば姿勢を出せる トルクと角速度の関係は単純ではない

100.

動画 衝撃的な事実

101.

動画 期待した動き 実際の動き

102.

角速度ω 点p r 重心 v ある点pにおける速度vは 重心からのベクトルrと 角速度ωと垂直なので v = !⇥ r と外積で表せる

103.

角速度ω 点p r v v = !⇥ r f 重心 速度vで移動している点pは 働いた力fの結果そうなっている

104.

トルクT f f f f 点p r 重心 f トルクTは すべての点で働いた力fを 距離を考慮して合計したもの 外積 r×f をぜんぶ足す T= X X r⇥f はぜんぶ足すの意味

105.

角速度ω トルクT r 重心 f 質点の分布が対称でない場合 トルクT(r×f の総計)と 角速度ω(運動の結果)は 軸が異なる

106.

動画 慣性テンソルの性質

107.

X r⇥f T =トルクと力の関係 v = !⇥ r 速度と角速度の関係 dv f= m 運動方程式 dt

108.

X r⇥f T =トルクと力の関係 v = !⇥ r 速度と角速度の関係 dv f= m 運動方程式 dt X d r ⇥ m ( !⇥r) T= トルクと角速度の関係! dt

109.

X d r ⇥ m ( ⇥r) T= トルクと角速度の関係! dt d! 右辺はベクトル dt を線形変換している この変換は必ず行列 I とおけて(計算略) d! T= I dt トルクと角速度の関係

110.

慣性テンソルとは d! T= I dt この I すなわち トルクベクトルと角速度ベクトルを関連づける 行列(2階テンソル)のこと 複雑な状況を行列ひとつで吸収できる驚異

111.

参考 ~r ⇥ (~! ⇥ ~r) = (~r · ~r)~! = |~r|2 ! ~ (~r · ! ~ )~r (rx !x + ry !y + rz !z )~r0 1 ~ ⇥ (B ~ ⇥ C) ~ A ~ · C) ~ B ~ (A ~ · B) ~ C ~ = (A rx = |~r|2 ! ~ (rx !x + ry !y + rz !z ) @ ry A rz 0 2 1 密度と rx ! x + rx ry ! y + rz rx ! z = |~r|2 ! ~ @ rx ry !x + ry2 !y + ry rz !z A 物体形状で を 2 rz r x ! x + r y rz ! y + r z ! z 0 2 10 1 積分したものが rx rx ry rz rx !x ry2 ry r z A @ ! y A = (rx2 + ry2 + rz2 )~ ! @ rx r y !z rz r x r x r y rz2 0 [email protected] ry2 rz2 + rx r y rz rx rx r y rx2 + rz2 ry rz 1 rz rx ry rz A ! ~ rx2 + ry2 慣性テンソル I

112.

例:直方体の慣性テンソル 0 @ ry2 rz2 + rx ry r z rx m abc Z rx ry rx2 + rz2 ry rz c 2 c 2 Z b 2 b 2 m 2 = (b + c2 ) 12 0 [email protected] Z y 1 r z rx ry rz A rx2 + ry2 a 2 c b (y 2 + z 2 )dxdydz a 2 m 2 12 (b + c2 ) 0 0 x a z 9要素すべてを計算 1 0 0 m 2 2 A (c + a ) 0 12 m 2 2 0 (a + b ) 12

113.

さて Rigidbody.inertiaTensor Rigidbody.inertiaTensorRotation これはなんだ

114.

型が… Vector3 Rigidbody.inertiaTensor Rigidbody.inertiaTensorRotation Quaternion どういうこっちゃ

115.

行列は二種類ある 対角化できるか、できないかだ! 慣性テンソルは対角化できる行列

116.

0 = a00 @ a10 a20 0 b00 @ b10 b20 a01 a11 a21 b01 b11 b21 1 対角化とは a02 a12 A a22 10 b02 A00 b12 A @ 0 b22 0 0 A11 0 10 0 b00 0 A @ b10 A22 b20 対角行列 対角行列に変換する術 b01 b11 b21 1 b02 b12 A b22 1

117.

0 = I Ir a00 @ a10 a20 0 b00 @ b10 b20 a01 a11 a21 b01 b11 b21 1 a02 a12 A a22 10 b02 A00 b12 A @ 0 b22 0 0 0 b00 0 A @ b10 A22 b20 Id A11 0 10 b01 b11 b21 Ir 1 1 b02 b12 A b22 1

118.

0 = I Ir a00 @ a10 a20 0 b00 @ b10 b20 a01 a11 a21 b01 b11 b21 1 a02 a12 A a22 10 b02 A00 b12 A @ 0 b22 0 0 0 b00 0 A @ b10 A22 b20 Id A11 0 10 b01 b11 b21 Ir I = IrIdIr 1 1 b02 b12 A b22 1 1

119.

I = IrIdIr 1 Id Rigidbody.inertiaTensor 対角行列なのでVector3で表現可能 Ir Rigidbody.inertiaTensorRotation 回転行列なのでQuaternionで表現可能

120.

動画 具体的に慣性テンソルを使う

121.
[beta]
public class SimpleRotator : MonoBehaviour {
void Update() {
if (Input.GetMouseButton(0)) {
var rb = GetComponent<Rigidbody>();
var omega = new Vector3(0f, 1f, 0f);
var R = transform.rotation;
var RI = Quaternion.Inverse(transform.rotation);
var Id = rb.inertiaTensor;
var Ir = rb.inertiaTensorRotation;
var IrI = Quaternion.Inverse(Ir);
var torque = R * Ir * Vector3.Scale(Id, IrI * RI * omega);
rb.AddTorque(torque, ForceMode.Impulse);
}
}
}

鉛直の角速度をもたらすトルクを得るサンプル
(現在の姿勢も考慮したもの)

122.

白く塗装した2つの球。 片方は純金製、 片方は純銀製。 素材を特定する方法は? ・色、形、大きさは同じ ・質量、重心も同じ ・純金製の球は中空(上図) ・純銀製の球は稠密(下図)

123.

答え 転がす 同じ質量なら中空の純金製のほうが 慣性テンソルが大きい。よって 回転しにくいほうが純金製

124.

おしまい