【Unity】Space Graphics Toolkit で太陽系の惑星の動きを再現しよう

太陽系の惑星 Unity
太陽系の惑星

Unity の Space Graphics Toolkit で、太陽系の惑星の動きを再現してみました。

Space Graphics Toolkit で太陽系の惑星の動きを再現しよう

太陽系の惑星
太陽系の惑星

YouTube

完成動画になります。

Asset Store

Space Graphics Toolkit

Solar System Pack のインポート

Space Graphics Toolkit のドキュメントから、無料の Solar System Pack をダウンロードして、プロジェクトにインポートします。

Space Graphics Toolkit - Documentation - 4.2.14
Solar System Pack
Solar System Pack

Horizons System

Horizons System から、太陽系の各惑星のデータを取得します。

Horizons System

Horizons System の App タブを開きます。
取得したい対象のデータを指定して、「Generate Ephemeris」ボタンを押すと、惑星の質量、座標、速度などが取得できます。
今回は、太陽系の座標ということで、太陽と地球の距離を基準とするAU単位で扱います。
Horizons System でデータを取得するときに、「5 Table Settings」で custom を選択し、Output units で au and days を選択しましょう。

au and days
au and days

SolarSystem の実装

ヒエラルキーに SolarSystemオブジェクトを追加します。
下記のスクリプトを作成して、SolarSystemオブジェクトに追加します。

using System;
using UnityEngine;

/// <summary>
/// 太陽系の惑星の動きをシミュレートする.
/// </summary>
public class SolarSystem : MonoBehaviour {
    [SerializeField]
    private Planet[] planets;
    private const double G = 2.959122e-4; // AU^3 / (M☉·day²).
    private float scaleTime = 0.1f; // 時間経過のスケール.
    private float scaleRadius = 1.0f; // 惑星の半径のスケール.

    private void FixedUpdate() {
        for (int i = 0; i < planets.Length; i++) {
            if (i == 0) {
                // 太陽.
                if (planets[i].model != null) {
                    // 太陽は大きいので20倍で固定にしておく.
                    float scaleRadiusSun = 20f;
                    planets[i].model.transform.localScale = Vector3.one * (planets[i].radius * scaleRadiusSun);
                }
                continue;
            }
            Vector3 acc = Vector3.zero;
            for (int j = 0; j < planets.Length; j++) {
                if (i != j) {
                    Vector3 direction = planets[j].position - planets[i].position;
                    float distanceSquared = direction.sqrMagnitude;
                    float distance = Mathf.Sqrt(distanceSquared);
                    if (distance > 0) {
                        // 万有引力の法則.
                        acc += direction * (float)(G * planets[j].mass) / (distance * distance * distance);
                    }
                }
            }
            planets[i].velocity += acc * Time.fixedDeltaTime * scaleTime;
            planets[i].position += planets[i].velocity * Time.fixedDeltaTime * scaleTime;
            if (planets[i].model != null) {
                planets[i].model.transform.position = planets[i].position;
                planets[i].model.transform.localScale = Vector3.one * (planets[i].radius * scaleRadius);
            }
        }
    }

    [Serializable]
    public class Planet {
        public float mass; // 太陽の質量を1とする.
        public Vector3 position; // au and days.
        public Vector3 velocity; // au and days.
        public GameObject model; // 3D model of the planet.
        public float radius; // AU単位.
    }
}

まとめ

Unity の Space Graphics Toolkit を使用して、太陽系の惑星の動きを再現してみました。
太陽系を扱う場合は、太陽と地球の平均距離を1とするAU単位を使うと便利ということが分かりました。
太陽系だけを見ても、宇宙は何もない空間が多いのだなと感じました。
宇宙がどうやってできているのかを、これからも勉強していきたいと思います。

コメント

タイトルとURLをコピーしました