Unity ARで物体を積み上げる!
前回は、UnityのARで
物体を投げました。
ARで物体を投げる。
今回は、前回の続きから
投げた物体を積み上げれ
るようにします。
※前回からの続きのため、
キューブを投げ方等は
省いています。そのため、
他の設定については、前回
のものを見ていただけると
助かります。
Unity ARで物体を積み上げる!MeshColliderの設定
「Hierarchy」-「Plane Generator」の
Inspectorを見ます。
その中に、「DetectedPlaneVisualizer」
があります。これは、ARで平面を検出した
際に出てくるオブジェクトです。
ここにMesh Collider(衝突判定)を付けることで、
物体を積み上げることができます。
「DetectedPlaneVisualizer」 を選択して、
Inspectorを開きます。
![](https://otaku-tomo.com/wp-content/uploads/2020/04/image-2.png)
「Add Component」から「Mesh Collider」を
追加します。
(追加の方法は、 「Mesh Collider」 を検索
もしくは「Phisics」の中にあります。)
![](https://otaku-tomo.com/wp-content/uploads/2020/04/image-3.png)
上記の様に追加できましたら、「Convex」の
チェックは外してください。
チェックがついていると、ほかのMeshCollider
と衝突する可能性があるためです。
MeshColliderの詳細は以下のリンクからご覧
ください。
MeshColliderについて
Unity ARで物体を積み上げる!スクリプトの設定
「DetectedPlaneVisualizer」 を選択して、
Inspectorを開きます。
InspectorのScriptである「DetectedPlaneVisualizer」
を開きます。
![](https://otaku-tomo.com/wp-content/uploads/2020/04/image-4.png)
以下の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で物体を積み上げる!実行
編集でしたら、アンドロイドにビルドして、
実行します。
平面を認識して積み上げることができました。
読んでいただきありがとうございます。
不明点等ありましたら、コメントに
お願いいたします。
コメント