Nexus Lab. Blog

0から始めるUnity物理演算①物理シミュレーションを"書く"

f:id:nexusyuumilo:20180126170353j:plain


今日のブログはネクサスではなく、私 Milo がお送りします!
この連載では、Unity道場で勉強したことを元に物理演算の基本を解説します。
今回は第1回。積分の理解と、簡単なコードでの物理シミュレーション実装にチャレンジしてみましょう!



この記事を書いたひと
工学部の学生。寝るのが好き。


この連載のバックナンバー

数は多いけどそれぞれ読みやすいです。

第1回:積分 ⇦イマココ!

第2回:FixedUpdate

nexusyuumilo.hateblo.jp

  • 処理落ちが発生した時Unityはどうなっているのか?
  • deltaTimeとfixedDeltaTimeの意味と違い

第3回:力と加速度(公開待ち)

  • 運動方程式って何?
  • 日本一わかりやすい&詳しい「質量」の話(まぁ、ホーキング大先生には負けるがね)

第4回:浮力(執筆中)

  • 浮力の実装は難しい!
  • 世界一簡単な浮力の実装!

第5回:衝突と力積(公開待ち)

  • ちょっと厄介な衝突
  • Impulseで解決!

第6回: 慣性テンソル(執筆中


なお、本記事で使用するデータの権利はユニティ・テクノロジーズ・ジャパンhttps://unity3d.com/jpに帰属します。
問題があれば記事はすぐに削除させていただきます。

いざ会場へ

1月25日、会場は六本木。地下鉄に乗るのは久しぶりだったので乗り換えに失敗しつつ、やっと到着!
 

f:id:nexusyuumilo:20180126100356j:plain
会場はこんな感じ

ほとんどが男性で、しかもmac使いが圧倒的多数!やはりUnityはMacユーザーが多いんですね。
ざっと見た感じ大学生は全くおらず、若干のアウェー感。
時間になると、Unity teamsの宣伝の後、講師の安原裕二さんが登壇されました!

積分がキホン!

いよいよ本題!ここからは安原さんが話していたことも書いていくので、講義のスライドを見ながらですと理解しやすいです!


講義はいきなりクイズから始まりました。

「純銀の玉と純金の玉を区別するにはどうしたら良いか」

f:id:nexusyuumilo:20180126175917p:plain

ただし条件として、色、形、大きさが同じ。そして、金の方が比重が重いので、その分中身をくりぬいてある。つまり質量も同じ!

安原さんの「あっ、溶かしちゃダメですよ!」で会場は和やかなムードになりましたww

答えの発表は講義の後!とのことで、皆さんも考えてみてね。

f:id:nexusyuumilo:20180126105516p:plain

安原さんは「数学に苦手意識を持たないで」と強調し、「皆さん、小学校の時にすでに積分の難しさはスルーしてるんです。面積を求める計算が長さ×長さ。よくわからないけどスルーしたでしょ。だから、積分もそんな感じで!」とおっしゃってました。

そして「微小ながさ」であるdxが初登場。講義ではこの「微小な量」が何回も登場します。

f:id:nexusyuumilo:20180126165435p:plain

積分とは、小さい部分をいっぱい集めて足すこと。球の体積を求める時は、うす〜いdxの厚みの円を集めればいい。その時の計算はコンピュータにお任せ!と言う感じの内容でした。ちょうど予備校で高校生に微分積分を教えているのですが、安原さんの説明を参考にしようと思いましたww

物理シミュレーションのスクリプティング

積分が終わると、テーマは「物理シミュレーションの最小実装」に。なんとRigidBodyを使わずに、C#スクリプトで物理シミュレーションを実現しよう!とのこと。
f:id:nexusyuumilo:20180126180435p:plain

ここで加速度、速度、位置と積分の関係が出てきます。

積分の凄さ

なんで積分するかと言うと、加速度がわかれば積分計算によって速度も位置もわかるからです。
f:id:nexusyuumilo:20180126181007p:plain

そして、実は僕たち人間が物体の運動を予想する時、加速度」って言う一番聞きなれないものしか役に立たないからです。

例えば車🚘、アクセル全開の車が、3分後にどこの位置にいるか?を考えましょう。
「今」の位置は定規で測ればわかるけど、3分後どこにいるかは速度がないとわからない。「今」の速度をはかっても、3分の間にアクセル踏んで加速しちゃうので意味がない。ところが加速度をゲットしてそれを積分すれば、速度が増える分も考慮して、3分後の位置がわかるんです。
加速度をゲットすれば、速度も位置もわかるというのが大事なポイントです!
 

物理シミュレーションのスクリプト

さて、実際の物理シミュのコードがスライド25枚目にあります。自分でも実装したかったのでコードを書き写しました。これをRigidbodyコンポーネントの代わりに任意のObjectに追加するだけで最小の物理シミュレーションとなります!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MyRigidbody : MonoBehaviour {
	public Vector3 acceleration;	//加速度。これがないと物理シミュレーションは始まらない。

	public Vector3 velocity;	//速度。微小時間dtの間の加速度を、積分でいっぱい集めると速度になる

	public Vector3 position;	//位置は速度の時間積分

	//追加部分始め----------------------------------------
	public float mass;	//質量に相当。
	public Vector3 gravityScale;	//重力加速度
	//追加部分終わり---------------------------------------

	const float dt = 1f/60f;	//微小時間dtに相当する部分
	public void AddForce(Vector3 force) {
		acceleration += force;	//加速度を増やすには、力を加えれば良い!
	}
	
	void FixedUpdate () {

		//追加部分始め---------------------------------------
		acceleration += mass * gravityScale;	//重力を発生させる。重力は質量と重力加速度の掛け算で求まる力!
		//追加部分終わり---------------------------------------

		velocity += acceleration * dt;	//加速度を時間積分
		position += velocity * dt;	//速度を時間積分

		//地面と接触したら、跳ね返る表現。
		//地面との衝突判定の代わりに、地面に近いところまで落ちたら速度を反転している。
		if(position.y < 0.5f) {
			velocity = -velocity;
		}
		transform.position = position;
		acceleration = Vector3.zero;	//加速度をリセット。加えた力の影響を最後にリセット	
	}
}


なお、コードの追加部分は重力の実装となっています!
このコードには2箇所だけインチキが含まれているのですが、第3回でちゃんと訂正します。

図のようにinspectorから初期位置、質量mass、重力加速度gravityScaleの値を設定すると、バウンドするオブジェクトを作れますよ!


f:id:nexusyuumilo:20180126121604p:plain

今日のまとめ

  • 物理シミュレーションは、計算の賜物。
  • 積分は、細かいものをたくさん集めること。
  • 物体の位置や速度を求めるには、加速度がわかれば良い!

次回はFixedUpdateについて、

  • 処理落ちが発生した時Unityはどうなっているのか?
  • deltaTimeとfixedDeltaTimeの意味と違い

について説明します。