【Unity】円や球の内部のランダムな座標を取得する

こじゃらこじゃら

円の中に均等に散らばるようにキャラを配置したい場合はどうすればいいの?

このはこのは

Unity提供の乱数APIを使えば簡単だわ。

円や球の内側のランダムな座標を取得する方法の紹介です。

結論を述べると、円の場合はRandom.insideUnitCircleプロパティ、球の場合はRandom.insideUnitSphereプロパティから内側のランダムな座標が取得できます。

var posCircle = Random.insideUnitCircle;
var posSphere = Random.insideUnitSphere;

得られるランダム位置は、均等な確率で分布している(連続一様分布)といった特徴があります。

ただし、範囲は半径1、中心が原点と固定されているため、任意の半径と中心としたい場合は一工夫が必要です。

本記事では、指定された半径と中心の円と球の内部にオブジェクトをランダム配置することを例にとって、使い方を解説していきます。

動作環境
  • Unity2021.2.0f1

スポンサーリンク

円の内側のランダム座標を取得する

Random.insideUnitCircleプロパティから取得できます。

参考:Random-insideUnitCircle – Unity スクリプトリファレンス

範囲は半径1中心は原点(0, 0)の円です。戻り値は、Vector2型の2次元空間上の座標となります。

任意の半径にしたい場合は、次のように半径を戻り値に掛けます。

float radius;

・・・(中略)・・・

// 指定された半径の円内のランダム位置
var circlePos = radius * Random.insideUnitCircle;

また、中心点をずらしたい場合は、次のように結果に値を足します。

float radius;
Vector2 center;

・・・(中略)・・・

// 指定された半径と中心の円内のランダム位置
var circlePos = radius * Random.insideUnitCircle + center;

3次元空間上に座標を変換したい場合は、座標をVector3変数にマッピングします。

float radius;
Vector3 center;

・・・(中略)・・・

// 指定された半径の円内のランダム位置
var circlePos = radius * Random.insideUnitCircle;

// XZ平面で指定された半径、中心点の円内のランダム位置を計算
var spawnPos = new Vector3(
    circlePos.x, 0, circlePos.y
) + center;

上記の例は、XZ平面上の円となります。

サンプルスクリプト

指定された半径と中心点の円の内側にオブジェクトをランダムで配置するサンプルスクリプトです。

RandomCircleSpawner.cs
using UnityEngine;

public class RandomCircleSpawner : MonoBehaviour
{
    // 円の半径
    [SerializeField] private float _radius = 1;

    // 円の中心点
    [SerializeField] private Vector3 _center;

    // 配置するPrefab
    [SerializeField] private GameObject _prefab;

    private void Update()
    {
        // マウス左ボタンがクリックされたら
        if (Input.GetMouseButtonDown(0))
        {
            // 指定された半径の円内のランダム位置を取得
            var circlePos = _radius * Random.insideUnitCircle;

            // XZ平面で指定された半径、中心点の円内のランダム位置を計算
            var spawnPos = new Vector3(
                circlePos.x, 0, circlePos.y
            ) + _center;

            // Prefabを追加
            Instantiate(_prefab, spawnPos, Quaternion.identity);
        }
    }
}

XZ平面でオブジェクトを配置するようにしました。左クリックする度にオブジェクトが一つ配置されます。

実行結果

球の内側のランダム座標を取得する

Random.insideUnitSphereプロパティから取得できます。

参考:Random-insideUnitSphere – Unity スクリプトリファレンス

範囲は半径1中心(0, 0, 0)の球です。戻り値はVector3型の位置となります。

任意の半径と中心点の球を取得範囲としたい場合は、次のように戻り値を加工します。

float radius;
Vector3 center;

・・・(中略)・・・

// 指定された半径、中心点の球内のランダム位置を取得
var spawnPos = radius * Random.insideUnitSphere + center;

この辺は円と同じ要領です。

サンプルスクリプト

指定された半径と中心点の球の内側にオブジェクトをランダムで配置するサンプルスクリプトです。

RandomSphereSpawner.cs
using UnityEngine;

public class RandomSphereSpawner : MonoBehaviour
{
    // 球の半径
    [SerializeField] private float _radius = 1;

    // 球の中心点
    [SerializeField] private Vector3 _center;

    // 配置するPrefab
    [SerializeField] private GameObject _prefab;

    private void Update()
    {
        // マウス左ボタンがクリックされたら
        if (Input.GetMouseButtonDown(0))
        {
            // 指定された半径、中心点の球内のランダム位置を取得
            var spawnPos = _radius * Random.insideUnitSphere + _center;

            // Prefabを追加
            Instantiate(_prefab, spawnPos, Quaternion.identity);
        }
    }
}

使い方は円のサンプルスクリプトと同様です。

実行結果

さいごに

Random.insideUnitCircleRandom.insideUnitSphereよりそれぞれ円、球を範囲としたランダム位置を取得できます。

得られる位置は、範囲内で一様分布しています。

キャラクターをランダムな位置にスポーンさせたい場合など、様々な場面で活用できるでしょう。

参考サイト

スポンサーリンク