Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

1,701 views

Published on

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

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

Published in: Technology
  • Be the first to comment

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

  1. 1. フィールド・エンジニア 安原 祐二 仙台版
  2. 2. 積分 完全マスター
  3. 3. 4列 3個 3×4=12 3個×4列=12個
  4. 4. 4m 3m 3×4=12 3m×4m=12m2
  5. 5. 3m×4m=12m2 3×4=12 4m 3m 長さと長さを掛けると 面積?
  6. 6. ぜんぜん違う話! 12個 12m2 4列 3個 4m 3m
  7. 7. 3m×4m=12m2 3×4=12 4m 3m 長さと長さを掛けると 面積? 積分の神秘は これと同じ
  8. 8. 3 極小の長さぶんを
  9. 9. 3 範囲ぶん足す
  10. 10. 3m 単位が変わる 4m 12m2
  11. 11. 極小長さ: 方向の微小区間 (デルタ )という y x x dx x
  12. 12. で積分する 面積を出す y x x
  13. 13. 長さmを長さmで積分→面積m2
  14. 14. 長さmを長さmで積分→面積m 面積m を長さmで積分→体積m 2 2 3 積分すると必ず単位が変化する
  15. 15. 積分の計算には を使う 計算は呪文のようなもの 理解そのものとは無関係 (いんてぐらる) Z
  16. 16. 例:球の体積(部分) r S t V = Z t r Sdx = Z t r ⇡(r2 x2 )dx = ⇡[r2 x x3 3 ]t r = ⇡{r2 t t3 3 ( r2 r r3 3 )} = ( t3 3 + r2 t + 2 3 r3 )⇡ 円の面積を重ねる 呪文 理解 x y
  17. 17. 〜今回のおはなし〜 力積 慣性テンソル 最小実装 外力 接触
  18. 18. 物理シミュレーションの 最小実装
  19. 19. 加速度m/s を時間tで積分→速度m/s 2
  20. 20. 加速度m/s を時間tで積分→速度m/s 2 velocity += acceleration * dt;
  21. 21. 速度m/sを時間tで積分→位置m 加速度m/s を時間tで積分→速度m/s 2 velocity += acceleration * dt;
  22. 22. 速度m/sを時間tで積分→位置m 加速度m/s を時間tで積分→速度m/s 2 velocity += acceleration * dt; position += velocity * dt; これが物理シミュ
  23. 23. 動画 最小実装はこれだ!
  24. 24. 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. 25. Unityの物理更新と FixedUpdate
  26. 26. 1秒 60回 60fpsのゲームは 1秒に60回画面を更新している dt
  27. 27. 1秒 60回 60fpsのゲームは 1秒に60回画面を更新している dt
  28. 28. 余裕 1/60秒 余裕期間は待機 処理
  29. 29. 余裕 1/60秒
  30. 30. 余裕 1/60秒
  31. 31. 1/60秒 余裕
  32. 32. 1/60秒 余裕
  33. 33. 超過 1/60秒
  34. 34. 待機 1/60秒
  35. 35. 1/60秒 責任重大
  36. 36. Update FixedUpdate 物理計算 1/60秒 通常更新
  37. 37. FixedUpdate 物理計算 1/60秒 物理更新 通常更新 Update
  38. 38. FixedUpdate 物理計算 FixedUpdate 物理計算 物理更新は複数回実行される 物理更新 物理更新 責任重大 フレーム Update
  39. 39. FixedUpdate 物理計算 FixedUpdate 物理計算 Time.fixedDeltaTime Time.deltaTime 固定 変動 Updateは が変動 責任重大 フレーム ※TimeManagerの設定で事情は変化 Update dt
  40. 40. FixedUpdate 物理計算 FixedUpdate 物理計算 OnCollision*は    から OnCollisionEnter OnCollisionExit OnTriggerEnter 物理更新
  41. 41. 外力
  42. 42. :力 :質量 :加速度 F am= F m a 運動方程式
  43. 43. :力 :質量 :加速度 物理シミュレーションは 位置を知りたい 質量は固定なので 加速度は力 F am= F m a Fa m= 運動方程式
  44. 44. 速度m/sを時間tで積分→位置m 加速度m/s を時間tで積分→速度m/s 2 velocity += acceleration * dt; position += velocity * dt; これが物理シミュ 加速度があれば位置を出せる
  45. 45. 力ベクトルは足せる
  46. 46. FixedUpdate 物理計算 物理更新
  47. 47. 物理更新 FixedUpdate 物理計算
  48. 48. 物理更新 FixedUpdate 物理計算 摩擦力 反発力 重力 AddForce +) トータル外力 足す 様々な力を
  49. 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. 50. 外力の応用 浮力
  51. 51. 浮力とは 物体が押しのけた水の重さ 潜っている部分の体積 かなりたいへん 潜っている部分の重心
  52. 52. 浮力の計算はたいへん 球で代用する 単純な式で出せる! 向きを考慮しなくていい 波の対応も容易
  53. 53. 動画 浮力っぽい
  54. 54. 浮力の計算はたいへん 球で代用する V = ( t3 3 + r2 t + 2 3 r3 )⇡ 単純な式で出せる! 向きを考慮しなくていい 波の対応も容易 r S t x y
  55. 55. 力積
  56. 56. 加速度は 微小期間の速度変化 m F m :力 :質量 :加速度 F= a a a dv dt = 運動方程式
  57. 57. 加速度は 微小期間の速度変化 mF= a a dv dt = mF= dv dt これも運動方程式
  58. 58. 加速度は 微小期間の速度変化 mF= dv dtmF = dvdt 力積 運動量(速度)の変化
  59. 59. 加速度は 微小期間の速度変化 mF= dv dtmF = dvdt 力積 力積も運動量も の変形に過ぎない F = ma 運動量(速度)の変化
  60. 60. F 「力積は運動量を変化させる」 dt期間に発生した力の合算を 速度変化に適用する術 m= dvdt
  61. 61. 瞬間的に発生する力に使う 「力積は運動量を変化させる」 dt期間に発生した力の合算を 速度変化に適用する術 m= dvdtF
  62. 62. 爆発で吹っ飛ばしたい 爆発力が存在する期間 AddForce を呼べばいい が、爆発は一瞬 が大き過ぎて一瞬を作れないdt
  63. 63. ForceMode.Impulse rigidbody.AddForce(force, ForceMode.Impulse);
  64. 64. ForceMode.Impulse rigidbody.AddForce(force, ForceMode.Impulse); 内部的には速度の直接変更 ( の右辺) 質量は考慮するが は考慮しない mF = dvdt dt
  65. 65. ForceMode.Impulse に依存しない速度変化になる OnCollisionEnterなどの瞬間的な力 rigidbody.AddForce(force, ForceMode.Impulse); 内部的には速度の直接変更 ( の右辺) 質量は考慮するが は考慮しない mF = dvdt dt dt
  66. 66. if (hit) { rb.AddForce(force); } if (hit) { rb.AddForce(force, ForceMode.Impulse); } 誤 正 を変えると動作が変わってしまう 瞬間的な外力には力積を使用する dt
  67. 67. Drag
  68. 68. Dragとは 速度に比例した抵抗力 例:空気抵抗
  69. 69. 指定終端速度 を得るための外力 [Unity]RigidbodyのDragから終端速度を得る https://qiita.com/yuji_yasuhara/items/1f438f0f27f5ef854a73参 考 :質量 :Drag m k F = 1 dt vmk k v F
  70. 70. 〜実践的な物理入門〜 https://www.youtube.com/watch?v=FqjM9oujyNE [Unity道場 札幌スペシャル] プロが教える脱初心者スクリプト術! 参 考
  71. 71. 物理シミュレーションの ウソ
  72. 72. 仮に物理シミュが完璧なら こんなに設定は必要ない
  73. 73. なにがウソなのか? あらゆる問題の根源 が大きすぎるdt
  74. 74. なにがウソなのか? が大きすぎる あらゆる問題の根源 物理シミュレーションの品質 あらゆる工夫dt
  75. 75. Wikipedia「Newton’s cradle」より 実現困難な例 https://en.wikipedia.org/wiki/Newton%27s_cradle
  76. 76. 接触
  77. 77. 接触していない 移動
  78. 78. 接触!(図形的に算出) 接触=必ず潜り込みが発生
  79. 79. 潜り込みを直す 位置と角度を調整 Solve(ソルブ) と呼ばれる処理
  80. 80. 接触は 物理シミュレーションの 最大の難関 多くの進化や工夫は ここに集約される
  81. 81. 下にも物体があったら 調整したせいで潜り込む!
  82. 82. 何度も調整 求める完全さは アプリの特徴次第 負荷大
  83. 83. 慣性テンソル
  84. 84. 「質量  」 F = m dv dt m m F v 外力 :速度v 質量は「動かしにくさ」
  85. 85. T = I d! dt 慣性テンソルは「回しにくさ」 回転ににおける「慣性テンソル 」 F = m dv dt 移動における「質量  」 m I m I T ! F v 外力 トルク :速度v :角速度!
  86. 86. 動画 慣性テンソルを可視化
  87. 87. 回しにくい 回しにくい 回しやすい
  88. 88. 外積 ここからは武装が必要 行列 テンソル トルク
  89. 89. 外積 〜ベクトルの立体関係〜 どちらのベクトルにも 垂直なベクトル A B A×B外積
  90. 90. B 行列 〜ベクトルに掛けるもの〜 BにPを掛けたらA AもBもひとつの値(スカラー)なら大きさしか変えない が、ベクトルの場合は大きさも方向も変えるのでPは行列 0 @ Ax Ay Az 1 A 0 @ Bx By Bz 1 A 0 @ P00 P01 P02 P10 P11 P12 P20 P21 P22 1 A= PA =
  91. 91. ベクトル スカラー 行列 0階テンソル 1階テンソル 2階テンソル 今回扱うのは2階テンソル 〜単なる呼びかた〜テンソル
  92. 92. 回転には必ず回転軸がある 〜回転力の記述〜トルク トルク(と角速度)は 軸ベクトルで表現 回転させる力をトルクと呼ぶ
  93. 93. 速度m/sを時間tで積分→位置m 加速度m/s を時間tで積分→速度m/s 2 velocity += acceleration * dt; position += velocity * dt; これが物理シミュ 再掲 加速度があれば位置を出せる
  94. 94. 加速度があれば位置を出せる 加速度があれば(速度を出せるから)位置を出せる
  95. 95. トルクがあれば姿勢を出せる 加速度があれば位置を出せる 加速度があれば(速度を出せるから)位置を出せる
  96. 96. トルクがあれば姿勢を出せる 加速度があれば位置を出せる トルクから角速度を出せば姿勢を出せる 加速度があれば(速度を出せるから)位置を出せる
  97. 97. トルクがあれば姿勢を出せる 加速度があれば位置を出せる トルクから角速度を出せば姿勢を出せる 加速度があれば(速度を出せるから)位置を出せる トルクと角速度の関係は単純ではない
  98. 98. 動画 衝撃的な事実
  99. 99. 期待した動き 実際の動き 動画
  100. 100. 重心 r 角速度ω ある点pにおける速度vは 重心からのベクトルrと 角速度ωと垂直なので と外積で表せる v 点p v = ! ⇥ r
  101. 101. 重心 r 角速度ω 速度vで移動している点pは 働いた力fの結果そうなっている f m dv dt = f v = ! ⇥ r v 点p
  102. 102. 重心 r トルクT トルクTは すべての点で働いた力fを 距離を考慮して合計したもの 外積 r×f をぜんぶ足す X はぜんぶ足すの意味 T = X r ⇥ f ff f f f 点p
  103. 103. 質点が対称でない場合 トルクT(r×f の総計)と 角速度ω(運動の結果)は 軸が異なる 重心 r トルクT f 角速度ω
  104. 104. 動画 慣性テンソルの性質
  105. 105. v = ! ⇥ r f = m d dt (! ⇥ r) f = m dv dt 角速度と速度の関係 運動方程式 力と角速度の関係!
  106. 106. T = X r ⇥ f f = m d dt (! ⇥ r) T = X r ⇥ m d dt (! ⇥ r) 力とトルクの関係 力と角速度の関係 トルクと角速度の関係!
  107. 107. トルクと角速度の関係 T = X r ⇥ m d dt (! ⇥ r) T = I d! dt I 右辺はベクトル を線形変換している この変換は必ず行列  とおけて d! dt (計算略)
  108. 108. この すなわち トルクベクトルと角速度ベクトルを関連づける 行列(2階テンソル)のこと 慣性テンソルとは I T = I d! dt 複雑な状況を行列ひとつで吸収できる驚異
  109. 109. ~A ⇥ ( ~B ⇥ ~C) = ( ~A · ~C) ~B ( ~A · ~B) ~C ~r ⇥ (~! ⇥ ~r) = (~r · ~r)~! (~r · ~!)~r = |~r|2 ~! (rx!x + ry!y + rz!z)~r = |~r|2 ~! (rx!x + ry!y + rz!z) 0 @ rx ry rz 1 A = |~r|2 ~! 0 @ r2 x!x + rxry!y + rzrx!z rxry!x + r2 y!y + ryrz!z rzrx!x + ryrz!y + r2 z!z 1 A = (r2 x + r2 y + r2 z)~! 0 @ r2 x rxry rzrx rxry r2 y ryrz rzrx rxry r2 z 1 A 0 @ !x !y !z 1 A = 0 @ r2 y + r2 z rxry rzrx rxry r2 x + r2 z ryrz rzrx ryrz r2 x + r2 y 1 A ~! 参考 密度と 物体形状で  を 積分したものが 慣性テンソル I
  110. 110. 0 @ r2 y + r2 z rxry rzrx rxry r2 x + r2 z ryrz rzrx ryrz r2 x + r2 y 1 A x y z a b c m abc Z c 2 c 2 Z b 2 b 2 Z a 2 a 2 (y2 + z2 )dxdydz = m 12 (b2 + c2 ) I = 0 @ m 12 (b2 + c2 ) 0 0 0 m 12 (c2 + a2 ) 0 0 0 m 12 (a2 + b2 ) 1 A 例:立方体の慣性テンソル 9要素すべてを計算
  111. 111. Rigidbody.inertiaTensor Rigidbody.inertiaTensorRotation これはなんだ さて
  112. 112. Rigidbody.inertiaTensor Rigidbody.inertiaTensorRotation どういうこっちゃ 型が… Vector3 Quaternion
  113. 113. 慣性テンソルは対角化できる行列 行列は二種類ある 対角化できるか、できないかだ!
  114. 114. 0 @ A00 0 0 0 A11 0 0 0 A22 1 A 0 @ b00 b01 b02 b10 b11 b12 b20 b21 b22 1 A 対角化とは0 @ a00 a01 a02 a10 a11 a12 a20 a21 a22 1 A 対角行列に変換する術 対角行列 0 @ b00 b01 b02 b10 b11 b12 b20 b21 b22 1 A 1 =
  115. 115. 0 @ A00 0 0 0 A11 0 0 0 A22 1 A 0 @ b00 b01 b02 b10 b11 b12 b20 b21 b22 1 A 0 @ a00 a01 a02 a10 a11 a12 a20 a21 a22 1 A 0 @ b00 b01 b02 b10 b11 b12 b20 b21 b22 1 A 1 = IdIr I Ir 1
  116. 116. 0 @ A00 0 0 0 A11 0 0 0 A22 1 A 0 @ b00 b01 b02 b10 b11 b12 b20 b21 b22 1 A 0 @ a00 a01 a02 a10 a11 a12 a20 a21 a22 1 A 0 @ b00 b01 b02 b10 b11 b12 b20 b21 b22 1 A 1 = IdIr I Ir 1 I = IrIdIr 1
  117. 117. Rigidbody.inertiaTensor Rigidbody.inertiaTensorRotation 対角行列なのでVector3で表現可能 回転行列なのでQuaternionで表現可能 Id Ir I = IrIdIr 1
  118. 118. 動画 具体的に慣性テンソルを使う
  119. 119. 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); } } } 鉛直の角速度をもたらすトルクを得るサンプル (現在の姿勢も考慮したもの)
  120. 120. おしまい

×