【问题标题】:Tango/Unity - UI not blocking touches on screenTango/Unity - UI 不阻止屏幕上的触摸
【发布时间】:2017-04-01 00:45:58
【问题描述】:

我们正在构建一个类似于“小猫 - 在 AR 中放置虚拟对象”的示例,如下所示:

https://developers.google.com/tango/apis/unity/unity-howto-placing-objects.

基本上,当您触摸屏幕时,一只小猫会出现在现实世界的平面(地板)上。

在我们的应用中,我们有一个侧边菜单,带有几个按钮,每个按钮都显示不同的游戏对象。我们想要检测屏幕上任何地方的触摸,除了有 UI 的地方。我们希望 UI 在 Tango 中阻止触摸,并且只允许触摸在没有 UI 元素的屏幕区域上实例化相关的游戏对象。

触摸专用代码在这里:

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

PlacePictureFrame()在触摸位置放置一个相框对象。)

我找不到任何结合了触摸和 UI 的 Tango 示例。我尝试了一种名为 LeanTouch 的资产来阻止 UI 元素后面的触摸,但它似乎不适用于 Tango。请帮忙!

我已经尝试过使用方法5:

How to detect events on UI and GameObjects with the new EventSystem API

虽然它确实将PhysicsRaycaster 添加到TangoARCamera(标记为MainCamera),但无论您触摸屏幕的哪个位置,OnPointerDown 方法都不会生成调试日志。 Tango 是一个特例,所以这不是一个重复的问题。见下文:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class PictureFrameUIController : MonoBehaviour, IPointerClickHandler {

    public GameObject m_pictureFrame;
    private TangoPointCloud m_pointCloud;

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

    void addPhysicsRaycaster() {
        PhysicsRaycaster physicsRaycaster = GameObject.FindObjectOfType<PhysicsRaycaster>();
        if (physicsRaycaster == null) {
            Camera.main.gameObject.AddComponent<PhysicsRaycaster>();
        }
    }

    public void OnPointerClick(PointerEventData eventData) {
        Debug.Log("Clicked: " + eventData.pointerCurrentRaycast.gameObject.name);
        PlacePictureFrame(eventData.pointerCurrentRaycast.screenPosition);
    }


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

    void PlacePictureFrame(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 picture frame on the surface, and make it always face the camera.
        if (Vector3.Angle(plane.normal, Vector3.up) > 60.0f && Vector3.Angle(plane.normal, Vector3.up) < 140.0f) {
            Vector3 forward = plane.normal;
            // Vector3 right = Vector3.Cross(plane.normal, cam.transform.forward).normalized;
            // Vector3 forward = Vector3.Cross(right, plane.normal).normalized;
            Instantiate(m_pictureFrame, planeCenter, Quaternion.LookRotation(forward, Vector3.up));
        } else {
            Debug.Log("surface is not steep enough for picture frame to be placed on.");
        }
    }

    public void DeleteAllFrames() {
        GameObject[] frames = GameObject.FindGameObjectsWithTag("Frame");
        if (frames == null) {
            return;
        }
        foreach (GameObject frame in frames) {
            Destroy(frame);
        }
    }
}

【问题讨论】:

  • 这是重复的。如果该解决方案对您有用,那么您应该使用您在该解决方案中尝试过的内容提出这个问题。请用您从该解决方案中尝试的内容更新您的问题。也包括课程。
  • 我做到了。没有答案,因为您已经将其标记为重复。您的解决方案与 Tango 无关。
  • 再次,您应该使用“不起作用”的代码更新您的问题。您从 方法 5 尝试的代码。该代码应附加到您检测到点击的游戏对象。您必须显示该代码,以便人们可以帮助您。
  • 嗨@Programmer,如果你将它添加到尚未实例化的游戏对象中,将如何调用任何事件?我已按照您的建议添加了课程。
  • 我不明白您的最后评论,但请稍等。您可以将该脚本附加到您要检测点击的对象上,看看Debug.Log 是否正常工作?

标签: c# unity3d google-project-tango


【解决方案1】:

如果您想检测屏幕上除 UI 控件/组件之外的任何位置的点击,您必须使用EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId) 检查指针是否在 UI 上方。

如果在桌面上,请使用EventSystem.current.IsPointerOverGameObject()。您正在使用 Tango,所以EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)。应该使用。

void Update()
{
    if (Input.touchCount == 1)
    {
        //Trigger placepictureframe function when single touch ended.
        Touch t = Input.GetTouch(0);
        if (t.phase == TouchPhase.Ended)
        {
            //Make sure that pointer is not over UI before calling  PlacePictureFrame
            if (!EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
            {
                PlacePictureFrame(t.position);
            }
        }
    }
}

编辑:

这似乎只适用于TouchPhase.Began

更改 t.phase == TouchPhase.Ended to t.phase == TouchPhase.Began 这应该可以按预期工作。确保使用移动设备/探戈而不是鼠标进行测试。

【讨论】:

  • 嗯,不幸的是,这不起作用。触摸时,它仍在 UI 对象后面放置相框。
  • 嗨,我看了,把t.phase == TouchPhase.Ended改成t.phase == TouchPhase.Began。这就是问题所在。我不明白为什么它不适用于t.phase == TouchPhase.Ended
  • 你我的朋友是他妈的枪!有效!谢谢!
  • 不客气。如果您的问题得到解决,请不要忘记accept这个答案。
  • @Programmer if (!EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))...这还能用吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-05
  • 1970-01-01
  • 1970-01-01
  • 2014-09-27
  • 1970-01-01
  • 2016-08-13
  • 2015-05-11
相关资源
最近更新 更多