MRが楽しい

MRやVRについて学習したことを書き残す

指定のトランスフォームを中心にオブジェクトを回転させながら追従させる その3

本日は Unity の小ネタ枠です。
指定のトランスフォームを中心にオブジェクトを回転させながら追従させる方法を記事にします。
今回は指定のオブジェクトに徐々に近づけることで科学館でよく見る万有引力の動きをそれっぽく再現してみます。
f:id:bluebirdofoz:20210708233216j:plain

前提条件

前回記事の続きです。
bluebirdofoz.hatenablog.com
bluebirdofoz.hatenablog.com

Vector3.Lerp

直線上にある 2 つのベクトル間を補間します。
本記事では徐々にターゲットオブジェクト方向に近づけるために利用します。
docs.unity3d.com

public static Vector3 Lerp (Vector3 a, Vector3 b, float t);
引数 説明
a 開始位置
b 到達位置
t 移動割合(0.0~1.0)

サンプルシーン

以下の通り、サンプルスクリプトを修正しました。
ターゲットオブジェクトの周囲を中心に回転しながら、徐々にターゲットオブジェクトに近づいていきます。
そして距離が近づくほど、回転の速度が上昇していきます。
・RotateAroundTargetGravitation.cs

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

public class RotateAroundTargetGravitation : MonoBehaviour
{
    [SerializeField, Tooltip("開始位置オブジェクト")]
    private GameObject StartObject;

    [SerializeField, Tooltip("ターゲットオブジェクト")]
    private GameObject TargetObject;

    [SerializeField, Tooltip("開始時の回転速度係数")]
    private float SpeedFactor = 0.1f;

    [SerializeField, Tooltip("Lerp係数")]
    private float LerpFactor = 0.01f;

    [Tooltip("開始時の2点間の距離")]
    private float RadiusDistance;

    [Tooltip("回転軸")]
    // 回転軸はY軸(縦軸)に固定する
    private Vector3 RotateAxis = Vector3.up;

    private void Start()
    {
        // 各オブジェクト位置を取得する
        Vector3 startPosition = StartObject.transform.position;
        Vector3 targetPosition = TargetObject.transform.position;

        // 初期位置はスタートオブジェクトと同じ位置に設定する
        this.transform.position = startPosition;

        // 開始時の距離を取得する
        RadiusDistance = Vector3.Distance(startPosition, targetPosition);
    }

    // Update is called once per frame
    void Update()
    {
        if (StartObject == null || TargetObject == null) return;

        // 各オブジェクト位置を取得する
        Vector3 targetPosition = TargetObject.transform.position;
        Vector3 selfPosition = this.transform.position;

        // 現在の距離を取得する
        float currentRadiusDistance = Vector3.Distance(selfPosition, targetPosition);

        if (currentRadiusDistance < 0.1f)
        {
            // 一定以上に距離が近づいたら計算を終了する
            this.transform.position = TargetObject.transform.position;
            this.transform.rotation = TargetObject.transform.rotation;
            return;
        }

        // 距離が近づくほど回転速度を早くする
        float currentSpeedFactor = SpeedFactor * (RadiusDistance / currentRadiusDistance);

        // Leap関数を使って徐々にターゲットに近づいていく
        this.transform.position = Vector3.Lerp(selfPosition, targetPosition, LerpFactor);

        // 指定オブジェクトを中心に回転する
        this.transform.RotateAround(
            targetPosition,
            RotateAxis,
            360.0f / (1.0f / currentSpeedFactor) * Time.deltaTime
            );
    }
}

f:id:bluebirdofoz:20210708233330j:plain

シーンに Sphere オブジェクトを作成し、本スクリプトを追加します。
f:id:bluebirdofoz:20210708233344j:plain

追従させるターゲットとして Cube オブジェクトを配置し手指定します。
開始位置のターゲットには[MainCamera]を指定します。
f:id:bluebirdofoz:20210708233358j:plain

動作確認

シーンを再生して動作を確認します。
Sphere オブジェクトがカメラ位置から cube オブジェクトに向かって回転しながら落下していきます。
f:id:bluebirdofoz:20210708233427j:plain

距離が近づくほど回転速度が速くなり、ターゲットオブジェクトの位置に到達します。
f:id:bluebirdofoz:20210708233438j:plain