如何检测 UI 和游戏对象上的点击/触摸事件

2023-12-12

如何在android中检测Canvas on Touch上的UI对象?

例如,我有一个画布,其中有 5 个对象,例如Image, RawImage, Buttons, InputField等等。

当我触摸 Button UI 对象时然后执行某些操作。单击时,每个按钮都会执行不同的过程。

代码如下所示:

private void Update()
{
    if (Input.touches.Length <= 0) return;

    for (int i = 0; i < Input.touchCount; i++)
    {
        if (Button1.touch)
            if (Input.GetTouch(i).phase == TouchPhase.Began)
                login();
        else if (Button2.touch && Input.GetTouch(i).phase == TouchPhase.Began)
            LogOut();
    }
}

那么该怎么做呢?

第二: 如何检测Gameobject被触摸?是不是和上面的一样呢?


您不使用新 UI 的输入 API。您可以订阅 UI 事件或根据事件实现接口。

以下是检测新 UI 组件上的事件的正确方法:

1.Image, RawImage and Text成分:

实现所需的接口并覆盖其功能。下面的示例实现了最常用的事件。

using UnityEngine.EventSystems;

public class ClickDetector : MonoBehaviour, IPointerDownHandler, IPointerClickHandler,
    IPointerUpHandler, IPointerExitHandler, IPointerEnterHandler,
    IBeginDragHandler, IDragHandler, IEndDragHandler
{
    public void OnBeginDrag(PointerEventData eventData)
    {
        Debug.Log("Drag Begin");
    }

    public void OnDrag(PointerEventData eventData)
    {
        Debug.Log("Dragging");
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        Debug.Log("Drag Ended");
    }

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

    public void OnPointerDown(PointerEventData eventData)
    {
        Debug.Log("Mouse Down: " + eventData.pointerCurrentRaycast.gameObject.name);
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        Debug.Log("Mouse Enter");
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        Debug.Log("Mouse Exit");
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        Debug.Log("Mouse Up");
    }
}

2.Button成分:

您使用事件来注册按钮点击:

public class ButtonClickDetector : MonoBehaviour
{
    public Button button1;
    public Button button2;
    public Button button3;

    void OnEnable()
    {
        //Register Button Events
        button1.onClick.AddListener(() => buttonCallBack(button1));
        button2.onClick.AddListener(() => buttonCallBack(button2));
        button3.onClick.AddListener(() => buttonCallBack(button3));

    }

    private void buttonCallBack(Button buttonPressed)
    {
        if (buttonPressed == button1)
        {
            //Your code for button 1
            Debug.Log("Clicked: " + button1.name);
        }

        if (buttonPressed == button2)
        {
            //Your code for button 2
            Debug.Log("Clicked: " + button2.name);
        }

        if (buttonPressed == button3)
        {
            //Your code for button 3
            Debug.Log("Clicked: " + button3.name);
        }
    }

    void OnDisable()
    {
        //Un-Register Button Events
        button1.onClick.RemoveAllListeners();
        button2.onClick.RemoveAllListeners();
        button3.onClick.RemoveAllListeners();
    }
}

如果您检测到除“按钮单击”之外的其他内容,请使用方法 1。例如,“按钮按下”而不是“按钮单击”,请使用IPointerDownHandler和它的OnPointerDown方法 1 中的函数。

3.InputField成分:

您使用事件来注册来注册InputField提交:

public InputField inputField;

void OnEnable()
{
    //Register InputField Events
    inputField.onEndEdit.AddListener(delegate { inputEndEdit(); });
    inputField.onValueChanged.AddListener(delegate { inputValueChanged(); });
}

//Called when Input is submitted
private void inputEndEdit()
{
    Debug.Log("Input Submitted");
}

//Called when Input changes
private void inputValueChanged()
{
    Debug.Log("Input Changed");
}

void OnDisable()
{
    //Un-Register InputField Events
    inputField.onEndEdit.RemoveAllListeners();
    inputField.onValueChanged.RemoveAllListeners();
}

4.Slider成分:

要检测拖动过程中滑块值何时发生变化:

public Slider slider;

void OnEnable()
{
    //Subscribe to the Slider Click event
    slider.onValueChanged.AddListener(delegate { sliderCallBack(slider.value); });
}

//Will be called when Slider changes
void sliderCallBack(float value)
{
    Debug.Log("Slider Changed: " + value);
}

void OnDisable()
{
    //Un-Subscribe To Slider Event
    slider.onValueChanged.RemoveListener(delegate { sliderCallBack(slider.value); });
}

对于其他事件,请使用Method 1.

5.Dropdown成分

public Dropdown dropdown;
void OnEnable()
{
    //Register to onValueChanged Events

    //Callback with parameter
    dropdown.onValueChanged.AddListener(delegate { callBack(); });

    //Callback without parameter
    dropdown.onValueChanged.AddListener(callBackWithParameter);
}

void OnDisable()
{
    //Un-Register from onValueChanged Events
    dropdown.onValueChanged.RemoveAllListeners();
}

void callBack()
{

}

void callBackWithParameter(int value)
{

}

非 UI 对象:

6.对于 3D 对象(网格渲染器/任何 3D 碰撞器)

Add PhysicsRaycaster然后到相机使用方法 1 中的任何事件.

下面的代码会自动添加PhysicsRaycaster到主要Camera.

public class MeshDetector : MonoBehaviour, IPointerDownHandler
{
    void Start()
    {
        addPhysicsRaycaster();
    }

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

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

    //Implement Other Events from Method 1
}

7.对于 2D 对象(Sprite 渲染器/任何 2D 碰撞器)

Add Physics2DRaycaster然后到相机使用方法 1 中的任何事件.

下面的代码会自动添加Physics2DRaycaster到主要Camera.

public class SpriteDetector : MonoBehaviour, IPointerDownHandler
{
    void Start()
    {
        addPhysics2DRaycaster();
    }

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

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

    //Implement Other Events from Method 1
}

事件系统故障排除:

在 UI、2D 对象(Sprite 渲染器/任何 2D 碰撞器)和 3D 对象(网格渲染器/任何 3D 碰撞器)上未检测到点击:

A.检查您是否有EventSystem。如果没有 EventSystem,它根本无法检测点击。如果您没有,请自行创建。


Go to 游戏对象--->UI--->事件系统。如果事件系统尚不存在,这将创建一个。如果它已经存在,Unity 将忽略它。


B.UI 组件或带有 UI 组件的 GameObject 必须位于Canvas。这意味着一个Canvas必须是 UI 组件的父组件。如果没有这个,EventSystem 将无法运行并且不会检测到点击。

这仅适用于 UI 对象。它doesn't适用于 2D(精灵渲染器/任何 2D 碰撞器)或 3D 对象(网格渲染器/任何 3D 碰撞器)。


C.如果这是一个 3D 对象,PhysicsRaycaster未连接至相机。确保PhysicsRaycaster已连接至相机。看#6以上了解更多信息。


D.如果这是一个 2D 对象,Physics2DRaycaster未连接至相机。确保Physics2DRaycaster已连接至相机。看#7以上了解更多信息。


E.如果这是一个 UI 对象,您想要使用接口函数检测点击,例如OnBeginDrag, OnPointerClick, OnPointerEnter以及中提到的其他功能#1 then 带有检测代码的脚本必须附加到该 UI 对象你想检测点击。


F另外,如果这是您想要检测点击的 UI 对象,请确保其前面没有其他 UI 对象。如果您想要检测点击的 UI 前面有另一个 UI,它将阻止该点击。

要验证这不是问题,请禁用画布下的每个对象(除了您想要检测点击的对象),然后查看点击是否有效。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何检测 UI 和游戏对象上的点击/触摸事件 的相关文章

  • 从 PDF 转换为 HTML [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 强制枢轴项目在显示之前预加载

    我有一个带有多个 PivotItems 的 Pivot 其中一个包含一个画布 将其项目放置在动态位置 取决于数据 我获取数据 并且可以在用户选择该项目之前将这些项目放置在其位置 这不是第一个枢轴 但是 只有当我选择 PivotItem 时
  • 如何使 Window.Current 关闭后可见?

    我有一个可以打开新窗口的应用程序 如果原始窗口关闭 然后用户启动应用程序 例如从开始菜单 TryShowAsStandaloneAsync无法打开新窗口 为什么 所以我想 复活 原来的那个 但虽然我用Window Current Activ
  • crt0 是否加载 msvcrt.dll?

    我想弄清楚标准 C 函数是什么样的printf 在 Windows 环境下加载到内存中 我知道crt0 obj准备堆栈 调用int main int argc char argv 然后使用 main 返回的退出代码退出进程 我还听说 C 标
  • 在 C 中读取字符时打印

    我正在尝试编写一个简单的小代码片段来响应箭头键按下 我知道 up 由 A 表示 并且我有以下代码来检查该序列 while 1 input char fgetc stdin if input char EOF input char n bre
  • 将 python 字典翻译为 C++

    我有包含以下代码的 python 代码 d d 0 0 0 d 1 2 1 d 2 1 2 d 2 3 3 d 3 2 4 for i j in d print d i j d j i 不幸的是 对于我的目的来说 循环遍历 python 中
  • 通过 WCF 提供类对象的数组或列表

    任何提供自定义类对象列表或数组的 WCF 客户端服务器示例都会对我有所帮助 但这是我到目前为止所得到的 这是我想提供的班级系统 namespace NEN Server FS Serializable public class XFS pr
  • 调试器 StepInto 自动生成的代码和 JMC 问题

    我正在使用 MDBG 示例制作托管 NET 调试器 目前 我正在努力解决 StepInto 行为 而 StepOut 和 StepOver 似乎有效 实现Just My Code迈步我在呼唤SetJMCStatus在模块加载时 这工作得很好
  • .NET 4.0 进程中的 clr.dll!LogHelp_TerminateOnAssert

    背景 我正在开发一个基于 WinForm 的 NET 4 0 桌面应用程序 该应用程序几乎没有线程和计时器 并对用户控件使用一些 GDI 处理 在我的开发过程中 我通常会查看 sysinternal 的 Process Explorer 以
  • 保存到会话状态的 DataTable 丢失事件处理程序

    我有一个来自强类型数据集的数据表 该数据集在 TableNewRow 事件上有一个事件处理程序 用于初始化一些日期字段 当我将此表保存到会话状态时 事件处理程序会正常触发 直到表被序列化 在后续请求中 当我从会话状态检索表时 事件处理程序不
  • Tulpep PopupNotifier 无法与计时器一起使用

    using System using System Data SQLite using System Drawing using System Timers using System Windows Forms using Tulpep N
  • 将模型和订阅密钥传递给 LuisDialog,而不是通过属性

    我正在编写一个可以说两种语言的机器人 因此 我需要使用两个单独的 LUIS 应用程序 每种语言一个 Bot Framework 中的 LuisDialog 是这样初始化的 来自 Microsoft 的示例 LuisModel c413b2e
  • 使用日期时间作为文件名并随后解析文件名?

    我正在将文件写入硬盘 文件名是这样构建的 String Format 0 yyyy MM dd hh mm ss txt DateTime Now 例如 文件名是 2010 09 20 09 47 04 txt 现在我想在下拉列表中显示这些
  • JsonSerializer.Deserialize 失败

    考虑代码 using System using System Text Json public class Program public static void Main int id 9 string str id id var u Js
  • 为什么%c前面需要加空格? [复制]

    这个问题在这里已经有答案了 下面的代码一编译就给出了奇怪的o p main char name 3 float price 3 int pages 3 i printf nEnter names prices and no of pages
  • 为什么转发引用与右值引用具有相同的语法?

    我刚刚对这些 相当 新的功能做了一些研究 我想知道为什么 C 委员会决定为它们引入相同的语法 看来开发人员不必要浪费一些时间来理解它是如何工作的 而一种解决方案可以让我们思考进一步的问题 就我而言 它是从问题开始的 可以简化为 includ
  • 如何在 C# 中按进程获取打开文件句柄的列表?

    如何在 C 中通过进程 ID 获取打开文件句柄的列表 我也有兴趣挖掘并获取文件名 寻找与流程资源管理器所做的等效的编程 这很可能需要互操作 考虑到对此添加赏金 实现起来非常复杂 哎呀 这很难从托管代码中做到 有一个 大多数事情都可以在互操作
  • 迭代非增量枚举

    在你问之前 我已经looked https stackoverflow com questions 261963 c iterate through an enum and looked https stackoverflow com qu
  • 在 '*' 标记之前编译“错误:预期 ')' 时出现多个相同错误

    我正在尝试用 C 语言编程 当我使用以下参数进行编译时 gcc D BSD SOURCE Wall ansi pedantic g tokenizer c FileOccur c WordList c wordstat c indexer
  • 在 C++ 中,将 float 转换为 double 再转换回 float 是否给出相同的值

    假设在下面的代码中 float f1 double d1 static cast

随机推荐