【Unity】オブジェクトAの周りを廻るオブジェクトB

2025年6月4日

オブジェクトBがオブジェクトAの周りを等速で回転し、常にオブジェクトAを見ているスクリプトは以下のように作成できます。このスクリプトをオブジェクトBにアタッチします

using UnityEngine;

public class OrbitAround : MonoBehaviour
{
    public Transform target; // オブジェクトAのTransform
    public float orbitSpeed = 10f; // 回転速度
    public float distance = 5f; // 回転半径

    void Update()
    {
        // オブジェクトAを中心にオブジェクトBを回転させる
        Orbit();

        // オブジェクトBが常にオブジェクトAを向くようにする
        LookAtTarget();
    }

    void Orbit()
    {
        // 時間に基づいてオブジェクトBの新しい位置を計算
        float angle = orbitSpeed * Time.deltaTime;
        transform.RotateAround(target.position, Vector3.up, angle);

        // オブジェクトBをターゲットから一定の距離に維持
        Vector3 direction = transform.position - target.position;
        direction.Normalize();
        transform.position = target.position + direction * distance;
    }

    void LookAtTarget()
    {
        transform.LookAt(target);
    }
}
using UnityEngine;

/// <summary>
/// 指定した「target」を中心に、指定距離だけ離れて円形移動(回転)させるスクリプト。
/// Inspector 上で「初期角度(0~360°)」を設定することで、複数体を等間隔に配置可能。
/// </summary>
public class OrbitAround : MonoBehaviour
{
    [Header("――――――――――――――――――――――――")]
    [Header("〈回転の中心〉")]
    [Tooltip("回転の中心となる Transform。シーン上の任意のオブジェクトを指定できます。")]
    public Transform target;

    [Header("〈回転に関する設定〉")]
    [Tooltip("中心の周りを回る速さ(度/秒)。Inspector では度 (°) 単位で指定。")]
    public float orbitSpeed = 60f;

    [Tooltip("回転半径(中心からの距離)。")]
    public float distance = 2.0f;

    [Header("〈配置オフセット〉")]
    [Range(0f, 360f)]
    [Tooltip("このオブジェクトの初期角度(度)。\n" +
             "例:0, 120, 240 をそれぞれ設定すると等間隔に配置されます。")]
    public float initialAngle = 0f;

    // 内部で扱うラジアン表現の角度
    private float _angleRad;

    void Start()
    {
        if (target == null)
        {
            Debug.LogError("[OrbitAround] target が設定されていません。Inspector で中心にしたいオブジェクトの Transform をセットしてください。");
            enabled = false;
            return;
        }

        // Inspector で指定された「初期角度(度)」をラジアンに変換
        _angleRad = initialAngle * Mathf.Deg2Rad;

        // 初期フレーム時に位置を更新
        UpdatePosition();
    }

    void Update()
    {
        if (target == null) return;

        // 毎フレーム、orbitSpeed (°/s) をラジアンに変換して角度を加算
        float deltaAngleRad = orbitSpeed * Time.deltaTime * Mathf.Deg2Rad;
        _angleRad += deltaAngleRad;

        // 位置更新
        UpdatePosition();
    }

    /// <summary>
    /// _angleRad と距離 distance を使って transform.position を更新する
    /// </summary>
    private void UpdatePosition()
    {
        // 回転平面は XY 面を想定。Z はそのまま維持。
        float x = target.position.x + Mathf.Cos(_angleRad) * distance;
        float y = target.position.y + Mathf.Sin(_angleRad) * distance;
        float z = transform.position.z;

        transform.position = new Vector3(x, y, z);

        // 中心オブジェクトを常に向きたい場合は以下を有効化:
        // transform.up = (target.position - transform.position).normalized;
    }
}

プレハブ化した Enemy に OrbitAround スクリプトをあらかじめアタッチしておき、スクリプトで一括生成して等間隔に配置したい場合は、以下のように EnemySpawner クラスを用意すると便利です。

using UnityEngine;

/// <summary>
/// 指定した「target」を中心に、設定した数の Enemy を一括生成し、等間隔で回転させるサンプルスクリプト。
/// Prefab(EnemyOrbitPrefab)にはあらかじめ OrbitAround がアタッチされている想定。
/// </summary>
public class EnemySpawner : MonoBehaviour
{
    [Header("――――――――――――――――――――――――")]
    [Header("〈生成に関する設定〉")]
    [Tooltip("回転の中心になるオブジェクトの Transform をセット")]
    public Transform target;

    [Tooltip("OrbitAround がアタッチされた敵のプレハブ")]
    public GameObject enemyOrbitPrefab;

    [Tooltip("生成する敵の数(例:3 を指定すると 360/3 = 120° 間隔になります)")]
    [Range(1, 12)]
    public int enemyCount = 3;

    [Tooltip("回転半径")]
    public float distance = 2.0f;

    [Tooltip("回転速度(度/秒)」)
    public float orbitSpeed = 60f;

    void Start()
    {
        if (target == null || enemyOrbitPrefab == null)
        {
            Debug.LogError("[EnemySpawner] target または enemyOrbitPrefab が未設定です。");
            return;
        }

        // 等間隔に配置するための角度ステップ(度)
        float angleStep = 360f / enemyCount;

        for (int i = 0; i < enemyCount; i++)
        {
            // Prefab を target の位置に生成
            GameObject enemy = Instantiate(enemyOrbitPrefab, target.position, Quaternion.identity);

            // OrbitAround コンポーネントを取得
            OrbitAround orbitComp = enemy.GetComponent<OrbitAround>();
            if (orbitComp == null)
            {
                Debug.LogWarning("[EnemySpawner] 生成したプレハブに OrbitAround がアタッチされていません。");
                continue;
            }

            // 各パラメータを設定
            orbitComp.target       = target;
            orbitComp.distance     = distance;
            orbitComp.orbitSpeed   = orbitSpeed;
            orbitComp.initialAngle = i * angleStep;  // 例:0°, 120°, 240°
        }
    }
}
訪問数 31 回, 今日の訪問数 1回

Unity

Posted by hidepon