我试图在4个已知点之间动态创建一个平面。 4点是由用户触摸电话屏幕创建的,圆柱体放置在他们触摸的位置,非常类似于HelloAR教程,除了圆柱体而不是Andys。这是有效的,4缸开始创建。在假设情况下,用户将创建一个有4个点的正方形,比方说2米乘2米。然后我想动态地放置一个适合4个点的平面(它不必完全适合,只是大致)。使用adb我已经验证了调用了CreateBricks方法,并使用正确的转换实例化了该平面。我只是没有看到飞机被创造出来。
这是我的代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using GoogleARCore;
public class SceneController : MonoBehaviour {
public Camera firstPersonCamera;
public Text anchorcount;
public GameObject pointPrefab; //The cylinder prefab
public GameObject patioPrefab; //The plane prefab
public ArrayList pointArray;
private int anchorCount;
private bool m_IsQuitting = false;
private bool brickCreated = false;
// Use this for initialization
void Start () {
QuitOnConnectionErrors();
anchorCount = 0;
pointArray = new ArrayList();
brickCreated = false;
}
// Update is called once per frame
void Update () {
_UpdateApplicationLifecycle();
if (anchorCount < 4)
ProcessTouches();
else if(!brickCreated)
CreateBricks();
}
private void CreateBricks()
{
try
{
brickCreated = true;
Debug.Log("CreateBricks");
float dist1 = Vector3.Distance(((GameObject)pointArray[0]).transform.position, ((GameObject)pointArray[1]).transform.position);
float dist2 = Vector3.Distance(((GameObject)pointArray[0]).transform.position, ((GameObject)pointArray[3]).transform.position);
Debug.Log("dist1:" + dist1.ToString());
Debug.Log("dist2:" + dist2.ToString());
GameObject prefab;
prefab = patioPrefab;
// Instantiate Andy model at the hit pose.
var pointObject = Instantiate(prefab);
prefab.transform.position = ((GameObject)pointArray[0]).transform.position;
prefab.transform.position.Scale(new Vector3(dist1, 0.5f, dist2));
Debug.Log(prefab.transform.position.x.ToString() + " " + prefab.transform.position.y.ToString() + " " + prefab.transform.position.z.ToString());
}
catch (System.Exception ex)
{
Debug.Log(ex.Message);
}
}
void ProcessTouches()
{
Touch touch;
if (Input.touchCount != 1 ||
(touch = Input.GetTouch(0)).phase != TouchPhase.Began)
{
return;
}
// Raycast against the location the player touched to search for planes.
TrackableHit hit;
TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon |
TrackableHitFlags.FeaturePointWithSurfaceNormal;
if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
{
// Use hit pose and camera pose to check if hittest is from the
// back of the plane, if it is, no need to create the anchor.
if ((hit.Trackable is DetectedPlane) &&
Vector3.Dot(firstPersonCamera.transform.position - hit.Pose.position,
hit.Pose.rotation * Vector3.up) < 0)
{
Debug.Log("Hit at back of the current DetectedPlane");
}
else
{
// Choose the Andy model for the Trackable that got hit.
GameObject prefab;
prefab = pointPrefab;
// Instantiate Andy model at the hit pose.
var pointObject = Instantiate(prefab, hit.Pose.position, hit.Pose.rotation);
// Compensate for the hitPose rotation facing away from the raycast (i.e. camera).
//andyObject.transform.Rotate(0, k_ModelRotation, 0, Space.Self);
// Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
// world evolves.
var anchor = hit.Trackable.CreateAnchor(hit.Pose);
// Make Andy model a child of the anchor.
pointObject.transform.parent = anchor.transform;
pointArray.Add(pointObject);
anchorCount++;
anchorcount.text = "Points: " + anchorCount;
}
}
}
private void _UpdateApplicationLifecycle()
{
// Exit the app when the 'back' button is pressed.
if (Input.GetKey(KeyCode.Escape))
{
Application.Quit();
}
// Only allow the screen to sleep when not tracking.
if (Session.Status != SessionStatus.Tracking)
{
const int lostTrackingSleepTimeout = 15;
Screen.sleepTimeout = lostTrackingSleepTimeout;
}
else
{
Screen.sleepTimeout = SleepTimeout.NeverSleep;
}
if (m_IsQuitting)
{
return;
}
QuitOnConnectionErrors();
}
private void _ShowAndroidToastMessage(string message)
{
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject unityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
if (unityActivity != null)
{
AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
AndroidJavaObject toastObject = toastClass.CallStatic<AndroidJavaObject>("makeText", unityActivity,
message, 0);
toastObject.Call("show");
}));
}
}
void QuitOnConnectionErrors()
{
// Quit if ARCore was unable to connect and give Unity some time for the toast to appear.
if (Session.Status == SessionStatus.ErrorPermissionNotGranted)
{
_ShowAndroidToastMessage("Camera permission is needed to run this application.");
m_IsQuitting = true;
Invoke("_DoQuit", 0.5f);
}
else if (Session.Status.IsError())
{
_ShowAndroidToastMessage("ARCore encountered a problem connecting. Please start the app again.");
m_IsQuitting = true;
Invoke("_DoQuit", 0.5f);
}
}
}
通过在Instantiate对象中设置pointObject变量的父级来解决上述代码的问题。然后飞机相对于父对象出现。