【Unity道場スペシャル 2018仙台】物理シミュレーション完全マスター

1.2K Views

January 19, 18

スライド概要

2018/1/20に開催されたUnity道場スペシャル 2018仙台の講演スライドです。
講師:安原 祐二 (ユニティ・テクノロジーズ・ジャパン合同会社)

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

profile-image

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

シェア

またはPlayer版

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

関連スライド

各ページのテキスト
1.

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

2.

積分 完全マスター

3.

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

4.

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

5.

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

6.

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

7.

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

8.

3 極小の長さぶんを

9.

3 範囲ぶん足す

10.

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

11.

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

12.

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

13.

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

14.

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

15.

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

16.

例:球の体積(部分) 呪文 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

17.

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

18.

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

19.

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

20.

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

21.

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

22.

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

23.

動画 最小実装はこれだ!

24.
[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;
}
}

25.

Unityの物理更新と FixedUpdate

26.

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

27.

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

28.

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秒 通常更新 物理計算 FixedUpdate Update

37.

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

38.

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

39.

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

40.

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

41.

外力

42.

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

43.

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

44.

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

45.

力ベクトルは足せる

46.

物理計算 FixedUpdate 物理更新

47.

物理更新 物理計算 FixedUpdate

48.

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

49.

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をそれぞれ呼ぶのと同じ

50.

外力の応用 浮力

51.

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

52.

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

53.

動画 浮力っぽい

54.

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

55.

力積

56.

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

57.

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

58.

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

59.

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

60.

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

61.

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

62.

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

63.

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

64.

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

65.

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

66.

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

67.

Drag

68.

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

69.

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

70.

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

71.

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

72.

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

73.

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

74.

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

75.

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

76.

接触

77.

接触していない 移動

78.

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

79.

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

80.

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

81.

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

82.

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

83.

慣性テンソル

85.

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

86.

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

87.

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

88.

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

89.

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

90.

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

91.

行列 〜ベクトルに掛けるもの〜 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 A@ By A P22 Bz

92.

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

93.

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

94.

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

95.

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

96.

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

97.

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

98.

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

99.

動画 衝撃的な事実

100.

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

101.

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

102.

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

103.

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

104.

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

105.

動画 慣性テンソルの性質

106.

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

107.

力と角速度の関係 T = X T = r⇥f X d f = m (! ⇥ r) dt 力とトルクの関係 d r ⇥ m (! ⇥ r) dt トルクと角速度の関係!

108.

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

109.

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

110.

参考 ~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 =@ ry2 rz2 + rx r y rz rx rx r y rx2 + rz2 ry rz 1 rz rx ry rz A ! ~ rx2 + ry2 慣性テンソル I

111.

例:立方体の慣性テンソル 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 I=@ 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

112.

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

113.

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

114.

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

115.

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

116.

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

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 I = IrIdIr 1 1 b02 b12 A b22 1 1

118.

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

119.

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

120.
[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);
}
}
}

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

121.

おしまい