🐬

【Unity】BoxCastでボックス形のレイを飛ばして当たり判定を取る

2024/06/01に公開2

はじめに

公式ドキュメントはここで確認できます。
https://docs.unity3d.com/jp/current/ScriptReference/Physics.BoxCast.html
だだ、少しわかりにくいと感じたので、そっちを読んでわからない場合はこの記事を読んでみてください。メモ的なものなので説明は上手くないかもしれませんが。。

完成形


白いボックスがピンクのボックスの上に近づき、Ray(緑)が接触すると、半透明になります。
(わかりやすいようにRayを緑の線で可視化しています。)

コードも貼っておきます。

public class BoxCastTest : MonoBehaviour
{
    void Update()
    {
        RaycastHit hit;
        if (Physics.BoxCast(transform.position, (Vector3.one * 0.5f), new Vector3(0, -1, 0), out hit, Quaternion.identity, 1))
        {
            hit.collider.gameObject.GetComponent<MeshRenderer>().material.color = new Color(1, 0.7f, 0.7f, 0.1f);
        }
    }

    void OnDrawGizmos()
    {
        Gizmos.color = Color.green;
        Gizmos.DrawWireCube(transform.position + new Vector3(0, -1, 0), Vector3.one);
    }
}

引数

Physics.BoxCast(
    Vector3 center, (ボックスの中心)
    Vector3 halfExtents, (各軸についてのボックスサイズの半分)
    Vector3 direction, (ボックスを投射する方向)
    out RaycastHit hitInfo, (ヒット情報)
    Quaternion orientation, (ボックスの回転)
    float maxDistance (キャストの最大の長さ)
)

公式ドキュメントをみると引数はこんな感じになっています。(全てではない)
言葉だけなので、わかりづらいと思います。
画像を交えて説明します。

Vector3 center, (ボックスの中心)


「ボックスの中心」は少し言葉が悪いです。
Rayを飛ばし始める原点。今回は白いボックスの中心。

// Rayを飛ばすスクリプトを白いボックスにアタッチしている場合(自身の原点を指定)
this.transform.position
または
// 任意の座標
new Vector3(10, 10, 30)

Vector3 halfExtents, (各軸についてのボックスサイズの半分)


飛ばすRayのボックスサイズ。中心からの長さで指定。辺の長さではありません。
図のように、青色の線の長さをhalfExtentsに指定すると、飛ばすRayは緑色のボックスのサイズになります。(わかりやすいようにRayを緑の線で可視化しています。)
なので、1x1のボックスだとすると、半分の0.5を指定します。

new Vector3(0.5f, 0.5f, 0.5f)
または
Vector3.one * 0.5f

Vector3 direction, (ボックスを投射する方向)


Rayを飛ばす方向をベクトルで指定します。
例では下向きに飛ばしています。(-y)

new Vector3(0, -1, 0)

out RaycastHit hitInfo, (ヒット情報) 後述

話が長くなるので、最後に説明します。

Quaternion orientation, (ボックスの回転)


今回の例では回転させていないので、Quaternion.identity(回転なし)を指定しています。

// 回転なし
Quaternion.identity

// 回転あり
Quaternion.Euler(0f, 0f, 1.0f);

float maxDistance (キャストの最大の長さ)


center(Rayの原点)から、direction方向へのRayの長さ
例では、白いボックスは1x1なため、白いボックスとRayのボックスの距離は1を指定。
(ボックスの原点と原点の距離であることに注意)

out RaycastHit hitInfo, (ヒット情報)

ここまででRayを飛ばすことはできました。
次は当たり判定を取ってみます。

この引数を使用して、Rayが衝突した相手のオブジェクトの参照を受け取ることができます。

RaycastHit hit; // 受け取るためのお皿
if (Physics.BoxCast( , , , out hit, ,)) // お皿の場所を教える
{
    // 受け取ったオブジェクトで何らかの処理。
    hit.collider.gameObject.GetComponent<MeshRenderer>().material.color = new Color(1, 0.7f, 0.7f, 0.1f);
}

RaycastHitには有用な情報が他にも含まれていますが、今回は割愛します。
公式ドキュメントを貼っておきます。
https://docs.unity3d.com/ja/2020.3/ScriptReference/RaycastHit.html

ボックスの可視化について

Gizmosを使用して、デバッグスクリーンにボックスを描画することができます。
プレイ画面では表示されません。

public class BoxCastTest : MonoBehaviour
{
    void OnDrawGizmos()
    {
        // 緑色を指定
        Gizmos.color = Color.green;
        // DrawWireCubeでボックスを描画。
        Gizmos.DrawWireCube(transform.position + new Vector3(0, -1, 0), Vector3.one);
    }
}

言うまでもありませんが、第一引数は描画したいボックスの原点の場所。
第二引数はボックスのサイズです。BoxCastのサイズ指定方法とは異なり、各軸の辺の長さで指定します。1x1x1のボックスの場合はnew Vector3(1, 1, 1)を指定します。

// 1x1x1
new Vector3(1, 1, 1) 
// or 
Vector3.one

誤りがあれば教えてください。

Discussion

seisei89628seisei89628

どうせならnew Vector3(0,-1,0)も既存で定義されてるものを使いましょう。
new Vector3(0,-1,0) -> Vector3.down
ほかはうろ覚えですが確かこうです。
new Vector3(0,1,0) -> Vector3.up
new Vector3(1,0,0) -> Vector3.right
new Vector3(-1,0,0) -> Vector3,left
new Vector3(0,0,1) -> Vector3,forward
new Vector(0,0,-1) -> Vector3,back

知っていたら申し訳ないですが、他にはワールド軸ではなくオブジェクトの傾きに依存するローカル軸のとり方もあるので、気になったら調べて見て欲しいです。

zzzzzzzz

そうですね。使えるならそっちを使ってもいいです。
説明のために即値指定を使用しました。