地球上に立っている人が剛速球を投げて、地球を1回転して戻って来て自分でキャッチするための条件を確かめるためにUnityの物理エンジンでシミュレーションしようと思ったので、まずは自由に動き回れる惑星を実装してみた。ドラゴンボールの界王星みたいな感じ。
オブジェクトの配置
まず適当なプロジェクトを作り、直径30mほどの球を配置する。
Hierarchy - 3D Object - Sphere
- Positionは全て0
- Rotationは全て0
- Scale X: 30, Y:30, Z:30
オブジェクトにPlanet
という名前をつけておく。
目印用に適当にCubeをおいておく。
Hierarchy - 3D Object - Cube
- Position X:0, Y:17, Z:0
- Rotationは全て0
- Scaleは全て1
ComponentにRigidBody, Box Colliderをセット。独自の重力を実装するためUse Gravity
をオフにしておく。
次に操作するプレイヤーを作り、カメラを追従させる。だいぶ昔にやったことあるので、この辺のポストを参照。
Hierarchy - CreateEmpty
オブジェクトにPlayer
という名前をつける。
- Position X:0, Y:16, Z:-4
- Rotationは全て0
- Scaleは全て1
こちらもRigidBody, Box Colliderをセット。Use Gravity
をオフ。
Hierarchyビューから、Main Camera
をドラッグしてPlayer
の下に入れておく。
重力の実装
Use Gravity
をオフにしているのでこのままだと浮いた状態になっている。そこで、Planet
の中心に重力点があるようにスクリプトで実装する。
Player - Inspector - Add Component - New Script - Planet Gravity
PlayerGravity.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlanetGravity : MonoBehaviour { [SerializeField] private Transform sphereCenter; // 重力の中心 [SerializeField] private float gravityStrength = 9.8f; // 重力の強さ private float rotationSpeed = 50f; private Rigidbody rb; // Start is called before the first frame update void Start() { // このオブジェクトのRigidbodyを取得 rb = GetComponent<Rigidbody>(); // Rigidbodyがアタッチされていない場合、警告を表示 if (rb == null) { Debug.LogWarning("Rigidbodyがアタッチされていません。重力の適用にはRigidbodyが必要です。"); } } void FixedUpdate() { if (rb == null || sphereCenter == null) return; // 球の中心へのベクトルを計算(法線) Vector3 direction = (sphereCenter.position - transform.position).normalized; // 重力の力を計算 Vector3 gravityForce = direction * gravityStrength * rb.mass; // Rigidbodyに力を適用 rb.AddForce(gravityForce); // 法線ベクトルに従って、プレイヤーの縦方向のRotationを更新する Quaternion targetRotation = Quaternion.FromToRotation(-transform.up, direction) * transform.rotation; transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime); } }
同様にPlayerだけでなくCubeにもこのスクリプトをAttachしておく。
次に、Planet上を歩き回るコードを実装。
Player - Inspector - Add Component - New Script - WalkOnPlanet
WalkOnPlanet.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class WalkOnPlanet : MonoBehaviour { public Transform sphereCenter; // 球体の中心 public float speed = 5f; // プレイヤーの移動速度 public float rotationSpeed = 80f; // プレイヤーの回転速度 private Rigidbody rb; // Start is called before the first frame update void Start() { rb = GetComponent<Rigidbody>(); if (rb != null) { rb.useGravity = false; // Unityのデフォルトの重力を無効化 rb.constraints = RigidbodyConstraints.FreezeRotation; // 自動回転を防止 } } // Update is called once per frame void Update() { if (sphereCenter == null) return; // 入力の取得 float horizontal = Input.GetAxis("Horizontal"); float vertical = Input.GetAxis("Vertical"); // プレイヤーの移動 Vector3 movement = transform.forward * vertical; rb.MovePosition(rb.position + movement * speed * Time.deltaTime); transform.Rotate(Vector3.up, horizontal * rotationSpeed * Time.deltaTime); } }
これで上下キーで進行・後退、左右キーで向きを回転出来る。WASDキーでも動作する。
背景の変更
Unityのデフォルト背景だと、惑星上を移動したとき上下が変な感じになるので、上下がないような背景に変更する。今回は宇宙っぽい感じにしてみる。
Asset StoreにSkybox Series Freeというものがあったので、今回はこれを使ってみる。Open in Unityをして、開いたダイアログからImportする。
Skybox Series Free | 2D Sky | Unity Asset Store
importが済んだら、以下から設定する。
Window - Rendering - Lightning - Environment - Skybox Material - 6sidedCosmicCoolCloud
できたああああ!!