Unity
Rigidbody
VR
Unity入門
OculusGo

【OculusGo】我が家に太陽系がやって来た♬


※画像をクリックするとYouTube動画につながります

出来ました♬

太陽系のアプリ。。。まあ、2001年宇宙の旅のあの雰囲気がOculusGoのVRの中に再現。。。あれ??

ということで、中心力が支配的な自由な空間内の相互作用する物体の運動と呼べるようなものを作成できました。
※イメージはまさしく太陽系。。。です!

やったこと

(1)Cubeを配置
(2)C#Script
(3)相互作用と初期状態を考える
(4)Cubeをたくさん配置する
(5)遊んでみる

(1)Cubeを配置

OculusGo用設定は、これまでと同じなので省略します。
※当初OculusGoがフリーズして出荷状態に戻して再設定しましたが、それについてはあえて省略します

で、本論のCube配置について
以下のとおり設定しました。
Cube_settings.jpg
ここで大切なことは、これ太陽のつもりなので質量はめいっぱい大きくしました。
そして当たり判定を(0.5,0.5,0.5)にしています。
物体が当たると少し沈みます。
あと物体の色は赤っぽいのにしました。
rigidbodyの張り付け方は「Add Component-Physics-ridobody」で張り付けます。Use Gravityはチェック外してください。AngularDragは回転抵抗なので0、ほか以下のとおりです。
Mass - 質量
Drag - 抵抗(空気抵抗)
Angular Drag - 回転に対する抵抗
【参考】
GP11 チーム制作 03
Physic Materialも使ってみる。。とりあえず、0や1でいいと思うけど
Dynamic Friction - 動摩擦係数:0.6(0)
Static Friction - 静摩擦係数:0
Bounciness - 反射反発係数:0.8(1.0)
【参考】
PhysicMaterial.bounciness

(2)C#Script

①Forceが与えられなくて、結局Impulseにした
②相互作用は計算コストが半端なさそうでフリーズしたので、適当に中心力(しかも基本のばね)だけでCube間の相互作用はぶつかったときの物体の特性で代替した

が、以下のとおり結果は案外簡単。。。

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

public class moveCube : MonoBehaviour {

    [SerializeField]
    private GameObject obj;
    [SerializeField]
    private GameObject Cube;
    private Vector3 m_NewForce;

    // Use this for initialization
    void Start () {
        GameObject obj = Cube;
        this.obj.transform.GetComponent<Rigidbody>().AddTorque(new Vector3(0, 5f, 5f));
        // objに与える力を定義する。WorldSpaceの(0,0,10)に向かうベクトルに対して直角の方向に一定の力としている
        m_NewForce = new Vector3(-1000, 1000, 0);
        // objに力を加える
        this.obj.transform.GetComponent<Rigidbody>().AddForce(m_NewForce, ForceMode.Impulse);
    }
    // Update is called once per frame
    void Update () {
        obj.transform.GetComponent<Rigidbody>().AddTorque(new Vector3(0, 1f, 5f));
        // objに与える力を定義する。WorldSpaceの(0,0,10)に向かうベクトルに比例した力としている
        m_NewForce = new Vector3(-obj.transform.localPosition.x, -obj.transform.localPosition.y, -obj.transform.localPosition.z+10);
        // objに力を加える
        obj.transform.GetComponent<Rigidbody>().AddForce(m_NewForce, ForceMode.Impulse);
    }
}

(3)相互作用と初期状態を考える

ここで、初期条件の力を加える向きと大きさが本当は円運動させたかったが、まあちょっとそれぞれの初期位置と中心力の強さから計算しないとなので、いい加減にやった。
※あとで厳密にやって、もうちょっと真円に近い軌道のも作りたいと思う

実際のところ、きれいすぎるとぶつからない確率も上がるしね。。自然はもっと理不尽だという言い訳もあって。。
中心力を-kxにしたのもちょっと気が引けるけど、こういう計算昔見た気がするので、いいかも。。実際重力ってかなり理不尽な効き方する
※こちらは簡単にできるがやらなかった。。。以下の式でいけるはずだけど、なんか計算コスト高そう:フリーズ怖い(笑)

r2=Mathf.abs(obj.transform.localPosition.x*obj.transform.localPosition.x+obj.transform.localPosition.y*obj.transform.localPosition.y+obj.transform.localPosition.z*obj.transform.localPosition.z);
m_NewForce = new Vector3(-obj.transform.localPosition.x/r2, -obj.transform.localPosition.y/r2, -obj.transform.localPosition.z/r2+10);

(4)Cubeをたくさん配置する

これ驚きましたが、単にコピペというか
Hierachyで右クリックしてDupilicateするだけでどんどんできちゃいます。
しかも、自動的にすべての設定も踏襲するので変更する必要がありません。
あえて言えば同じところにコピペしちゃうので、初期条件を変える必要があります。
位置とMassを変更します。ほかのパラメーター、球体の大きさや画像を変えます。
特に面白いと思ったのは当たり判定は見かけの大きさと関係なく指定できます。
大きさも質量とは当然関係なく変えられるので、設定だけで結構面白いです。
※これがあるので、実は互いの相互作用を入れたくなって、
[SerializeField]
private GameObject Cube;
を残していますが、使っていません。
※最近接のCubeを取得できたら、やればいいと考えています

(5)遊んでみる

いろいろ変えて遊んでみると、見ているだけで楽しいです。
自然に運動する物体の理不尽さが伝わります。
ほんと、怖いです。
※これ見ていると結構ぶつかりますが、本物だと一度ぶつかったら終わりですから。。

まとめ

・太陽系っぽいアプリを作成して遊んでみた♬
・相互作用ははしょったが、大まかに太陽系が見えた
・辺縁系の小さな小惑星が衝突すると運動量を失って内惑星近傍の周回軌道に入る現象が見えた
・初期平面から軌道のずれた惑星や反対に回る惑星も案外出現していた

・初期条件と反発係数や動摩擦係数を調整すると長時間かからずに円盤状に回る現象にたどりつけるかも知れないと感じた
・物体間の近接相互作用(特に質量が大きい惑星)を入れると衛星をもつ惑星が作れそう
・今回やっていませんが、視点を変えられるように改善したいと思います。

※画像をクリックするとYouTube動画につながります