如何替换一个在空间中定位的AR对象?

4

按照这个教程,我可以在空间中定位一个物体。

如何在相同的位置替换该物体?我需要一个公共函数并将其分配给按钮,这样当我按下按钮时,“Kitty”模型会被其他模型替换。

以下是教程中的主要脚本:

using UnityEngine;
using System.Collections;

public class KittyUIController : MonoBehaviour
{
    public GameObject m_kitten;
    private TangoPointCloud m_pointCloud;

    void Start()
    {
        m_pointCloud = FindObjectOfType<TangoPointCloud>();
    }

    void Update ()
    {
        if (Input.touchCount == 1)
        {
            // Trigger place kitten function when single touch ended.
            Touch t = Input.GetTouch(0);
            if (t.phase == TouchPhase.Ended)
            {
                PlaceKitten(t.position);
            }
        }
    }

    void PlaceKitten(Vector2 touchPosition)
    {
        // Find the plane.
        Camera cam = Camera.main;
        Vector3 planeCenter;
        Plane plane;
        if (!m_pointCloud.FindPlane(cam, touchPosition, out planeCenter, out plane))
        {
            Debug.Log("cannot find plane.");
            return;
        }

        // Place kitten on the surface, and make it always face the camera.
        if (Vector3.Angle(plane.normal, Vector3.up) < 30.0f)
        {
            Vector3 up = plane.normal;
            Vector3 right = Vector3.Cross(plane.normal, cam.transform.forward).normalized;
            Vector3 forward = Vector3.Cross(right, plane.normal).normalized;
            Instantiate(m_kitten, planeCenter, Quaternion.LookRotation(forward, up));
        }
        else
        {
            Debug.Log("surface is too steep for kitten to stand on.");
        }
    }
}
2个回答

2

新增了一个方法ReplaceKitten <=在按钮点击时调用此方法
添加了一个public yourOtherModelGameObject,用于所需模型。
将实例化的小猫从PlaceKitten方法中全局化(放入变量)。

    using UnityEngine;
    using System.Collections;

    public class KittyUIController : MonoBehaviour
    {
        public GameObject m_kitten;
        public GameObject yourOtherModel; // could be prefab
        private TangoPointCloud m_pointCloud;
        private GameObject createdKitten;

        void Start()
        {
            m_pointCloud = FindObjectOfType<TangoPointCloud>();
        }

        void Update ()
        {
            if (Input.touchCount == 1)
            {
                // Trigger place kitten function when single touch ended.
                Touch t = Input.GetTouch(0);
                if (t.phase == TouchPhase.Ended)
                {
                    PlaceKitten(t.position);
                }
            }
        }
        //This method will disable the kitten and instantiate or place a GameObject on the same spot.
        public void ReplaceKitten()
        {
            GameObject modelToReplace;
            //Do this only if you will pass a Prefab to this Script
            modelToReplace = Instantiate(yourOtherModel);
            //Set your new object at the same coordinates and reset position
            modelToReplace.transform.parent = m_kitten.transform;
            modelToReplace.transform.position = new Vector3(0,0,0);
            //Disable kitten
            m_kitten.SetActive(false);
        }

        void PlaceKitten(Vector2 touchPosition)
        {
            // Find the plane.
            Camera cam = Camera.main;
            Vector3 planeCenter;
            Plane plane;
            if (!m_pointCloud.FindPlane(cam, touchPosition, out planeCenter, out plane))
            {
                Debug.Log("cannot find plane.");
                return;
            }

            // Place kitten on the surface, and make it always face the camera.
            if (Vector3.Angle(plane.normal, Vector3.up) < 30.0f)
            {
                Vector3 up = plane.normal;
                Vector3 right = Vector3.Cross(plane.normal, cam.transform.forward).normalized;
                Vector3 forward = Vector3.Cross(right, plane.normal).normalized;
                createdKitten = Instantiate(m_kitten, planeCenter, Quaternion.LookRotation(forward, up));
            }
            else
            {
                Debug.Log("surface is too steep for kitten to stand on.");
            }
        }
    }

请确保没有拼写错误,我不是编辑。


1
请注意,当您将文本变为黄色时,这意味着您在引用OP说的话并回复该话语。在您的答案中,您没有引用OP的话,因此我删除了引号。 - Programmer
非常感谢!但是出现了一个错误 - 看起来ReplaceKitten()不能接受“planeCenter”- http://imgur.com/a/n4l9J - Rumata
@Rumata 哦,是的,我现在看到没有声明 planeCenter。那个变量只是用来声明对象实例化的 position,我们之后会更改它。换句话说,尝试使用 Vector3.zero,它应该可以完成工作! - Hristo
@Hristo 能否请您详细解释一下?我尝试了:modelToReplace = Instantiate(yourOtherModel, Vector3.zero); 现在出现了多个错误:http://imgur.com/a/No3ub - Rumata
@Rumata 更新了代码,从 instantiate 的构造函数中移除了 Transform 父级。现在使用没有 _parent_ 的第一个构造函数。 - Hristo
显示剩余2条评论

0

保存您已实例化的对象的引用,并在您想要添加新对象时检查该实例是否为空,

如果不为空,则表示对象在空间中。销毁它并创建您想要的gameobject的新实例,并保存其引用。

如果为空,则表示空间为空,请创建一个新实例并保存其引用。

 public GameObject OtherModel;   // new model that you want to replace with kitty
 GameObject myRef;               // Reference for the object that is already in scene

    void PlaceKitten(Vector2 touchPosition)
    {
        // Find the plane.
        Camera cam = Camera.main;
        Vector3 planeCenter;
        Plane plane;
        if (!m_pointCloud.FindPlane(cam, touchPosition, out planeCenter, out plane))
        {
            Debug.Log("cannot find plane.");
            return;
        }

        // Place kitten on the surface, and make it always face the camera.
        if (Vector3.Angle(plane.normal, Vector3.up) < 30.0f)
        {
            Vector3 up = plane.normal;
            Vector3 right = Vector3.Cross(plane.normal, cam.transform.forward).normalized;
            Vector3 forward = Vector3.Cross(right, plane.normal).normalized;

            // Check whether we have already placed something or not
            if (myRef != null)
            {
                Transform temp = myRef.transform;
                Destroy(myRef);
                myRef = Instantiate(OtherModel, temp.position, temp.rotation);
            }
            else
            {
                myRef = Instantiate(m_kitten, planeCenter, Quaternion.LookRotation(forward, up));
            }
        }
        else
        {
            Debug.Log("surface is too steep for kitten to stand on.");
        }
    }

谢谢,但我理解在这种情况下,只有当我再次点击屏幕时它才会起作用。而且在这种情况下,很可能会出现一个略微不同的位置,那里还没有“Kitty”,我将继续克隆“Kitty”模型。而我需要的是只放置一次“Kitty”,然后通过点击按钮替换为其他模型(在相同的位置)。 - Rumata
不会,如果已经在空间中,则会克隆小猫,因为它首先会检查是否有小猫,如果没有,则会克隆,如果有小猫,则将使用myRef变量在相同位置克隆一个新的gameobject。请参见代码 :) - Nipun David

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接