以下の内容はhttps://bluebirdofoz.hatenablog.com/entry/2026/01/13/220134より取得しました。


Unityでゲームオブジェクトのメッシュ形状に合わせてBoundsを設定する

本日はUnityの小ネタ枠です。
Unityでゲームオブジェクトのメッシュ形状に合わせてBoundsを設定する方法です。

Bounds.Encapsulate

Bounds.EncapsulateはBoundsを拡張して別のBoundsを内包する最小限のBoundsを生成するメソッドです。
本メソッドを利用することで複数のBoundsを組み合わせて1つのBoundsを作成できます。
docs.unity3d.com

サンプルスクリプト

以下の指定されたオブジェクトが持つMeshRendererのBoundsを取得して見た目と同じ大きさのBoxColliderを生成するサンプルスクリプトを作成しました。
子オブジェクトの回転やスケールを考慮して全てのBoundsをBounds.Encapsulateで結合します。
・CalculateBoundsTest.cs

using UnityEngine;

public class CalculateBoundsTest : MonoBehaviour
{
    [SerializeField]
    private GameObject targetObject;

    [ContextMenu("Calculate Bounds")]
    void CalculateBounds()
    {
        // 子を含む全Rendererを取得
        var renderers = targetObject.GetComponentsInChildren<Renderer>(true);
        // 対象Rendererが存在しない場合は終了
        if (renderers.Length == 0)
        {
            return;
        }

        // ローカル空間での結合Boundsを構築
        var parentTransform = targetObject.transform;
        Bounds combinedLocalBounds = default;
        bool initialized = false;

        foreach (var renderer in renderers)
        {
            EncapsulateInLocalSpace(renderer.bounds, parentTransform, ref combinedLocalBounds, ref initialized);
        }

        // 対象のオブジェクトに同じサイズのBoxColliderを追加
        var boxCollider = targetObject.GetComponent<BoxCollider>();
        if (boxCollider == null)
        {
            boxCollider = targetObject.AddComponent<BoxCollider>();
        }
        boxCollider.center = combinedLocalBounds.center;
        boxCollider.size = combinedLocalBounds.size;
    }

    private void EncapsulateInLocalSpace(Bounds worldBounds, Transform parentTransform, ref Bounds localBounds, ref bool initialized)
    {
        // ワールド座標のBoundsを構成するパラメータを取得
        Vector3 extents = worldBounds.extents;
        Vector3 center = worldBounds.center;

        // バウンディングボックスの8頂点をローカル座標に変換しEncapsulate
        for (int ix = -1; ix <= 1; ix += 2)
        {
            for (int iy = -1; iy <= 1; iy += 2)
            {
                for (int iz = -1; iz <= 1; iz += 2)
                {
                    Vector3 cornerWorld = center + Vector3.Scale(extents, new Vector3(ix, iy, iz));
                    Vector3 cornerLocal = parentTransform.InverseTransformPoint(cornerWorld);

                    if (!initialized)
                    {
                        localBounds = new Bounds(cornerLocal, Vector3.zero);
                        initialized = true;
                    }
                    else
                    {
                        localBounds.Encapsulate(cornerLocal);
                    }
                }
            }
        }
    }
}

サンプルスクリプトをアタッチした以下のサンプルシーンを作成しました。
計算対象のルートオブジェクトをTargetObjectに指定します。

コンテキストメニューからCalculateBoundsTestを実行します。

以下の通り、子オブジェクトを含んだ見た目と同じ大きさのBoxColliderが設定されました。




以上の内容はhttps://bluebirdofoz.hatenablog.com/entry/2026/01/13/220134より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14