名古屋でアプリ・VR開発を行っています
ワクワクできるゲームをガンガン開発リリース中!

【Unity】ゲームオブジェクトのCenterの位置を求めてみた

こんにちは、SAT-BOXのコアラです。

今回は↓の記事の続きです。
sat-box.hatenablog.jp

前回の記事では、UnityのCenter座標がどう求められているかを調べました。
Center座標とは↓の画像の通り、PivotではなくCenterになっているときの操作の起点ですね。
f:id:sat-box:20181015172103p:plain

今回は、このCenter座標を求める処理を書いてきました。
早速載せます。

using UnityEngine;
public class Sample {
    
    public static Vector3 GetCenterPosition(Transform target)
    {
        //非アクティブも含めて、targetとtargetの子全てのレンダラーとコライダーを取得
        var cols = target.GetComponentsInChildren<Collider>(true);
        var rens = target.GetComponentsInChildren<Renderer>(true);

        //コライダーとレンダラーが1つもなければ、target.positionがcenterになる
        if (cols.Length == 0 && rens.Length == 0)
            return target.position;
        
        bool isInit = false;
        
        Vector3 minPos = Vector3.zero;
        Vector3 maxPos = Vector3.zero;

        for (int i = 0; i < cols.Length; i++)
        {
            var bounds = cols[i].bounds;
            var center = bounds.center;
            var size = bounds.size / 2;

            //最初の1度だけ通って、minPosとmaxPosを初期化する
            if (!isInit)
            {
                minPos.x = center.x - size.x;
                minPos.y = center.y - size.y;
                minPos.z = center.z - size.z;
                maxPos.x = center.x + size.x;
                maxPos.y = center.y + size.y;
                maxPos.z = center.z + size.z;

                isInit = true;
                continue;
            }
            
            if (minPos.x > center.x - size.x) minPos.x = center.x - size.x;
            if (minPos.y > center.y - size.y) minPos.y = center.y - size.y;
            if (minPos.z > center.z - size.z) minPos.z = center.z - size.z;
            if (maxPos.x < center.x + size.x) maxPos.x = center.x + size.x;
            if (maxPos.y < center.y + size.y) maxPos.y = center.y + size.y;
            if (maxPos.z < center.z + size.z) maxPos.z = center.z + size.z;
        }
        for (int i = 0; i < rens.Length; i++)
        {
            var bounds = rens[i].bounds;
            var center = bounds.center;
            var size = bounds.size / 2;

            //コライダーが1つもなければ1度だけ通って、minPosとmaxPosを初期化する
            if (!isInit)
            {
                minPos.x = center.x - size.x;
                minPos.y = center.y - size.y;
                minPos.z = center.z - size.z;
                maxPos.x = center.x + size.x;
                maxPos.y = center.y + size.y;
                maxPos.z = center.z + size.z;

                isInit = true;
                continue;
            }
            
            if (minPos.x > center.x - size.x) minPos.x = center.x - size.x;
            if (minPos.y > center.y - size.y) minPos.y = center.y - size.y;
            if (minPos.z > center.z - size.z) minPos.z = center.z - size.z;
            if (maxPos.x < center.x + size.x) maxPos.x = center.x + size.x;
            if (maxPos.y < center.y + size.y) maxPos.y = center.y + size.y;
            if (maxPos.z < center.z + size.z) maxPos.z = center.z + size.z;
        }

        return (minPos + maxPos) / 2;
    }
}

ちょっと長いので詳しい説明は省きますが、この関数にtransformを入れればCenter座標を取得できます。


これでCenter座標求められたわけですが、次はそれを活用する例を紹介します。


f:id:sat-box:20181112185741p:plain
ここに人間と額縁があります。


どう見ても人間と額縁ですね。


人間のPivotは足にあり、額縁は中央にあります。
まず単純に、人間を額縁に入れてみたいと思います。

using UnityEngine;
public class Sample : MonoBehaviour {
    public Transform frame;
    public Transform human;

    void Start()
    {
        human.position = frame.position;
    }
}

こうすると


f:id:sat-box:20181112190846p:plain
はみ出しましたね。

これを、Center座標を求めてやれば収まることでしょう。
処理はコチラ↓

using UnityEngine;
public class Sample : MonoBehaviour {
    public Transform frame;
    public Transform human;

    void Start()
    {
        //Center座標を求める
        Vector3 humanCenterPos = GetCenterPosition(human);

        //humanをどれだけ動かすと、Pivotの位置にCenterを持ってこられるか求める
        Vector3 centerDis = human.position - humanCenterPos;

        //frameの座標と、humanのPivotとCenterの位置の差を足せば完了
        human.position = frame.position + centerDis;
    }
    
    public static Vector3 GetCenterPosition(Transform target)... //略しました
}


結果は・・・


f:id:sat-box:20181112191417p:plain

頭ぶつけてますが、中央に来ていることが分かります。

このように、Center座標を使って位置を合わせたり色々なことに使えそうです。

以上です。