【Unity】角度の範囲を指定して円周上に配置する

投稿者: | 2020-09-16

シリンダーを中心とした円周上に赤いCubeを配置していきます。赤いCubeは白いCubeのある方向へ指定した距離だけ進んだところに置きますが、角度の範囲を指定しておいて、その外側に白いCubeがあるときは、範囲の境目に置きます。

まずシーンにシリンダーとCubeを1つずつ配置して、配置するためのCubeのプレハブを作ります。シリンダーの位置はワールドの中心でなくても問題ありません。

空のゲームオブジェクトを作ってスクリプトを付け、それらをアタッチします。

確認用のテキストも作ってアタッチしました。

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

public class edgeTest : MonoBehaviour
{
    [SerializeField] Transform center;
    [SerializeField] Transform target;
    [SerializeField] GameObject cube;
    [SerializeField] float distance = 1.7f;
    [SerializeField][Range(0,360)] int angleRange = 210;
    [SerializeField] Text text;

    // Start is called before the first frame update
    void Start()
    {
        text.text = "";

        StartCoroutine("SetCube");        
    }


    IEnumerator SetCube()
    {
        WaitForSeconds wait = new WaitForSeconds(0.8f);

        for (int i = 0; i < 50; i++)
        {
            yield return wait;

            Vector3 dir = Vector3.Normalize(target.position - center.position); // 中心からターゲットの方向
            float dot = Vector3.Dot(center.forward, dir); // 内積
            float angle = Mathf.Acos(dot) * Mathf.Rad2Deg; // 角度

            if (float.IsNaN(angle)) angle = 180; // 真後ろのとき

            Vector3 pos;

            // 内側の時
            if (angleRange / 2 >= angle || dir == center.forward)
            {
                pos = dir * distance + center.position;
                //pos = Quaternion.AngleAxis(angle, Vector3.Cross(center.forward, dir)) * (center.forward + center.position) * distance;
            }
            // 外側の時
            else
            {
                pos = Quaternion.AngleAxis(Vector3.Cross(center.forward, dir).y > 0 ? angleRange / 2 : -angleRange / 2, transform.up) * center.forward * distance + center.position;
            }

            Instantiate(cube, pos, cube.transform.rotation); // Cubeを生成

            text.text = i + 1 + "";         
        }
    }

}

スクリプトではまずシリンダーから白いCubeへの方向と、シリンダーの正面の方向との角度を調べて、それがインスペクタで指定する角度の範囲内かどうかによって、赤いCubeを配置する位置を変えます。

内側にあるときは白いCubeへの方向がわかればいいですが、外側の場合は、白いCubeがシリンダーから見て左右どちら側にあるかをVector3.Crossで調べる必要があります。

Vector3.Crossを使うと、フレミングの左手の法則で第1引数の方向を親指、第2引数を人差し指としたときの中指の指す方向がわかります。シリンダーと白いCubeが同じ高さにあれば、これが下を向くときは、その方向ベクトルのY座標はマイナスであり、白いCubeはシリンダーから見て左側にあるとわかります。参考:https://docs.unity3d.com/ja/current/ScriptReference/Vector3.Cross.html

シリンダーとCubeが同じ高さにないときは、変数にCubeの位置をいれてから、その変数のY座標をシリンダーに合わせるといいと思います。

赤いCubeが配置される範囲の中心はシリンダーの正面なので、シリンダーを横に回転させると、角度の範囲が移動します。

角度を360以上にすると全方向に赤いCubeを配置できます。

0にすると一箇所にしか配置されません。

マイナスだと、右側にあるときは左側の境界だけに、左側にあるときは右側の境界だけに配置されるようです。

コメントを残す

メールアドレスが公開されることはありません。