Unityを使うとコードをあれこれ書かなくても2D/3Dゲームを簡単につくることができます。Rigidbody を使うと、ゲームオブジェクトを物理特性によって制御する事ができるようになります。重力の影響を加えたり、それ以外の力を与えることでどのように動くかをシミュレーションすることができるようになるのです。
ボールを地面におとすと反発します。反発係数が1.0であれば永久にボールは跳ね続けます。実際には反発係数は1.0よりも小さいのでボールは動かなくなってしまうのですが、どれくらいの反発係数でどれくらいボールは跳ね続けるのでしょうか? Unityをつかってシミュレーションするプログラムをつくってみました。
まずUnityのプロジェクトをつくり、ヒエラルキーで「空のオブジェクトを作成」。するとGameObjectが生成されます。つぎにassetsを右クリックして「C#スクリプトを生成」、名前は適当でかまいません。スクリプトの名前は「GameObjectScript1」に変更しました。
GameObjectScript1をダブルクリックするとVisualStudioが立ち上がります。このとき「public class GameObjectScript1」と書かれている部分、クラス名はファイル名と同じにしてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
using System.Collections; using System.Collections.Generic; using UnityEngine; // スクリプトの名前を「GameObjectScript1」にしたらクラス名も「GameObjectScript1」にする public class GameObjectScript1 : MonoBehaviour { void Start() { } void Update() { } } |
これをヒエラルキーのGameObjectにドラッグアンドドロップしましょう。
次にこのファイルをもう一度開いて編集します。
まず床をつくります。球体の落下実験をしたいのですが、床がないと球体はそのままどこまでも落下してしまいます。
次に球体をつくります。場所はY座標5、Z座標0、X座標は少しずつ変更させて10個表示させます。球の大きさはlocalScaleはnew Vector3(0.7f, 0.7f, 0.7f);として1よりも少し小さい値にします。これは10個横に並べると幅をとるからでそれ以外にたいした意味はありません。
球を作ったらコンポーネントでRigidbodyとSphereColliderを追加します。Rigidbodyを追加することで重力の影響をうけます。
そのあと自作メソッド SetBouncinessを呼び出します。これは反発係数を設定するためです。最初は10個の球体に0から1.0までの値を設定しています。
Update()メソッドはとくに書くことはありません。これで実行してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
public class GameObjectScript1 : MonoBehaviour { void Start() { // 床をつくる GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane); plane.transform.position = new Vector3(0, 0, 0); plane.transform.rotation = Quaternion.Euler(0, 0, 0); plane.transform.localScale = new Vector3(1.7f, 1, 1); for (int i = 0; i <= 10; i++) { // 球をつくる GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); // 球の場所はY座標5、Z座標0、X座標は少しずつ変更させて10個の球を表示させます。 // 球のlocalScaleはnew Vector3(0.7f, 0.7f, 0.7f);を指定 float x = -5 + i * 1; sphere.transform.position = new Vector3(x, 5, 0); sphere.transform.rotation = Quaternion.Euler(0, 0, 0); sphere.transform.localScale = new Vector3(0.7f, 0.7f, 0.7f); sphere.AddComponent<Rigidbody>(); Rigidbody rigidbody = sphere.GetComponent<Rigidbody>(); sphere.AddComponent<SphereCollider>(); SetBounciness(sphere, i); } } void SetBounciness(GameObject sphere, int i) { SphereCollider sphereCollider = sphere.GetComponent<SphereCollider>(); sphereCollider.material.bounceCombine = PhysicMaterialCombine.Maximum; // 0.0-1.0 sphereCollider.material.bounciness = i * 0.1f; } void Update() { } } |
上記のコードを実行すると反発係数が0.6まではほとんど反発しないことがわかります。反発係数が1.0にすると永久に跳ね続けますが、ちょっとおかしな部分があります。だんだん跳ね上がる高さが高くなっていきます。これは物理学的にはありえないことです。物理学的現象に忠実再現することができるわけではないようです。
SetBouncinessメソッドを変化させれば反発係数の違いがどのように影響するかだいたいであればわかります。
0.6まではほとんど跳ねなかったので0.8から0.02刻みで実験してみましょう。SetBouncinessメソッドを以下のように書き換えます。
1 2 3 4 5 6 7 8 |
void SetBounciness(GameObject sphere, int i) { SphereCollider sphereCollider = sphere.GetComponent<SphereCollider>(); sphereCollider.material.bounceCombine = PhysicMaterialCombine.Maximum; // 0.80-1.00 sphereCollider.material.bounciness = 0.8f + i * 0.02f; } |
0.8から0.02刻みの実行結果
これなら0.9から0.01刻みで検証することができます。
1 2 3 4 5 6 7 8 |
void SetBounciness(GameObject sphere, int i) { SphereCollider sphereCollider = sphere.GetComponent<SphereCollider>(); sphereCollider.material.bounceCombine = PhysicMaterialCombine.Maximum; // 0.90-1.00 sphereCollider.material.bounciness = 0.9f + i * 0.01f; } |
0.9から0.01刻みの実行結果
だんだん跳ね上がる高さが高くなっていきます。これは物理学的にはありえないことです。物理学的現象に忠実再現することができるわけではないようです。
と書いていますがこれは恐らく重力で加速され続けているからではないでしょうか?
なので物理演算は正しい気がします