Unity ARで物体を積み上げる!

AR

Unity ARで物体を積み上げる!

前回は、UnityのARで
物体を投げました。
ARで物体を投げる。

今回は、前回の続きから
投げた物体を積み上げれ
るようにします。
※前回からの続きのため、
 キューブを投げ方等は
 省いています。そのため、
 他の設定については、前回
 のものを見ていただけると
 助かります。

Unity ARで物体を積み上げる!MeshColliderの設定

「Hierarchy」-「Plane Generator」の
Inspectorを見ます。
その中に、「DetectedPlaneVisualizer」
があります。これは、ARで平面を検出した
際に出てくるオブジェクトです。
ここにMesh Collider(衝突判定)を付けることで、
物体を積み上げることができます。
「DetectedPlaneVisualizer」 を選択して、
Inspectorを開きます。

「Add Component」から「Mesh Collider」を
追加します。
(追加の方法は、 「Mesh Collider」 を検索
もしくは「Phisics」の中にあります。)

上記の様に追加できましたら、「Convex」の
チェックは外してください。
チェックがついていると、ほかのMeshCollider
と衝突する可能性があるためです。
MeshColliderの詳細は以下のリンクからご覧
ください。
MeshColliderについて

Unity ARで物体を積み上げる!スクリプトの設定

「DetectedPlaneVisualizer」 を選択して、
Inspectorを開きます。
InspectorのScriptである「DetectedPlaneVisualizer」
を開きます。

以下の2文を追加してください。

        GetComponent<MeshCollider>().sharedMesh = null;
        GetComponent<MeshCollider>().sharedMesh = m_Mesh;

DetectedPlaneVisualizer に追加したコードが以下です。

namespace GoogleARCore.Examples.Common
{
    using System.Collections.Generic;
    using GoogleARCore;
    using UnityEngine;

    public class DetectedPlaneVisualizer : MonoBehaviour
    {
        private DetectedPlane m_DetectedPlane;

        private List<Vector3> m_PreviousFrameMeshVertices = new List<Vector3>();
        private List<Vector3> m_MeshVertices = new List<Vector3>();
        private Vector3 m_PlaneCenter = new Vector3();

        private List<Color> m_MeshColors = new List<Color>();

        private List<int> m_MeshIndices = new List<int>();

        private Mesh m_Mesh;

        private MeshRenderer m_MeshRenderer;

        public void Awake()
        {
            m_Mesh = GetComponent<MeshFilter>().mesh;
            m_MeshRenderer = GetComponent<UnityEngine.MeshRenderer>();
        }


        public void Update()
        {
            if (m_DetectedPlane == null)
            {
                return;
            }
            else if (m_DetectedPlane.SubsumedBy != null)
            {
                Destroy(gameObject);
                return;
            }
            else if (m_DetectedPlane.TrackingState != TrackingState.Tracking)
            {
                 m_MeshRenderer.enabled = false;
                 return;
            }

            m_MeshRenderer.enabled = true;

            _UpdateMeshIfNeeded();
        }

        public void Initialize(DetectedPlane plane)
        {
            m_DetectedPlane = plane;
            m_MeshRenderer.material.SetColor("_GridColor", Color.white);
            m_MeshRenderer.material.SetFloat("_UvRotation", Random.Range(0.0f, 360.0f));

            Update();
        }

        private void _UpdateMeshIfNeeded()
        {
            m_DetectedPlane.GetBoundaryPolygon(m_MeshVertices);

            if (_AreVerticesListsEqual(m_PreviousFrameMeshVertices, m_MeshVertices))
            {
                return;
            }

            m_PreviousFrameMeshVertices.Clear();
            m_PreviousFrameMeshVertices.AddRange(m_MeshVertices);

            m_PlaneCenter = m_DetectedPlane.CenterPose.position;

            Vector3 planeNormal = m_DetectedPlane.CenterPose.rotation * Vector3.up;

            m_MeshRenderer.material.SetVector("_PlaneNormal", planeNormal);

            int planePolygonCount = m_MeshVertices.Count;

            for (int i = 0; i < planePolygonCount; ++i)
            {
                m_MeshColors.Add(Color.clear);
            }

            const float featherLength = 0.2f;

            const float featherScale = 0.2f;

            for (int i = 0; i < planePolygonCount; ++i)
            {
                Vector3 v = m_MeshVertices[i];

                // Vector from plane center to current point
                Vector3 d = v - m_PlaneCenter;

                float scale = 1.0f - Mathf.Min(featherLength / d.magnitude, featherScale);
                m_MeshVertices.Add((scale * d) + m_PlaneCenter);

                m_MeshColors.Add(Color.white);
            }

            m_MeshIndices.Clear();
            int firstOuterVertex = 0;
            int firstInnerVertex = planePolygonCount;

            for (int i = 0; i < planePolygonCount - 2; ++i)
            {
                m_MeshIndices.Add(firstInnerVertex);
                m_MeshIndices.Add(firstInnerVertex + i + 1);
                m_MeshIndices.Add(firstInnerVertex + i + 2);
            }

            for (int i = 0; i < planePolygonCount; ++i)
            {
                int outerVertex1 = firstOuterVertex + i;
                int outerVertex2 = firstOuterVertex + ((i + 1) % planePolygonCount);
                int innerVertex1 = firstInnerVertex + i;
                int innerVertex2 = firstInnerVertex + ((i + 1) % planePolygonCount);

                m_MeshIndices.Add(outerVertex1);
                m_MeshIndices.Add(outerVertex2);
                m_MeshIndices.Add(innerVertex1);

                m_MeshIndices.Add(innerVertex1);
                m_MeshIndices.Add(outerVertex2);
                m_MeshIndices.Add(innerVertex2);
            }

            m_Mesh.Clear();
            m_Mesh.SetVertices(m_MeshVertices);
            m_Mesh.SetTriangles(m_MeshIndices, 0);
            m_Mesh.SetColors(m_MeshColors);

//最初にNULLを設定しないと反映されませんので、注意してください。
            GetComponent<MeshCollider>().sharedMesh = null;
            GetComponent<MeshCollider>().sharedMesh = m_Mesh;
        }

        private bool _AreVerticesListsEqual(List<Vector3> firstList, List<Vector3> secondList)
        {
            if (firstList.Count != secondList.Count)
            {
                return false;
            }

            for (int i = 0; i < firstList.Count; i++)
            {
                if (firstList[i] != secondList[i])
                {
                    return false;
                }
            }

            return true;
        }
    }
}

Unity ARで物体を積み上げる!実行

編集でしたら、アンドロイドにビルドして、
実行します。

平面を認識して積み上げることができました。

読んでいただきありがとうございます。
不明点等ありましたら、コメントに
お願いいたします。

コメント

タイトルとURLをコピーしました