Cómo detectar eventos de clic / toque en la interfaz de usuario y GameObjects

82

¿Cómo detectar un objeto UI en Canvas on Touch en Android?

Por ejemplo, tengo un lienzo que tienen 5 objetos tales como Image, RawImage, Buttons, InputFieldy así sucesivamente.

Cuando toco el objeto Button UI, luego hago algo. Cada botón realiza un proceso diferente cuando se hace clic en él, según.

El código se verá así:

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();
    }
}

Así que ¿cómo se hace?

Segundo: ¿Cómo detectar Gameobject get touch? ¿Es lo mismo con el anterior o no?

Dennis Liu
fuente

Respuestas:

171

No usa la API de entrada para la nueva interfaz de usuario. Te suscribes a los eventos de IU o implementas la interfaz según el evento.

Estas son las formas adecuadas de detectar eventos en los nuevos componentes de la interfaz de usuario:

1 . Image, RawImageY TextComponentes:

Implemente la interfaz necesaria y anule su función. El siguiente ejemplo implementa los eventos más utilizados.

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 . ButtonComponente:

Utiliza eventos para registrarse en los clics del botón:

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();
    }
}

Si está detectando algo que no sea un clic de botón en el botón, utilice el método 1. Por ejemplo, botón hacia abajo y no clic de botón, utilice IPointerDownHandlery su OnPointerDownfunción del método 1.

3 . InputFieldComponente:

Utiliza eventos para registrarse para registrarse para el envío de 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 . SliderComponente:

Para detectar cuándo cambia el valor del control deslizante durante el arrastre:

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); });
}

Para otros eventos, use el Método 1 .

5 . DropdownComponente

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)
{

}

OBJETOS QUE NO SON UI:

6 .Para objetos 3D (renderizador de malla / cualquier colisionador 3D)

Agregue PhysicsRaycastera la cámara y luego use cualquiera de los eventos del Método 1 .

El siguiente código se agregará automáticamente al archivo PhysicsRaycasterprincipal 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 .Para objetos 2D (Sprite Renderer / cualquier 2D Collider)

Agregue Physics2DRaycastera la cámara y luego use cualquiera de los eventos del Método 1 .

El siguiente código se agregará automáticamente al archivo Physics2DRaycasterprincipal 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
}

Solución de problemas del EventSystem:

No se detectaron clics en la interfaz de usuario, objetos 2D (Sprite Renderer / cualquier 2D Collider) y objetos 3D (Mesh Renderer / cualquier 3D Collider):

A .Compruebe que tiene EventSystem. Sin EventSystem, no puede detectar clics en absoluto. Si no lo tiene, créelo usted mismo.


Vaya a GameObject ---> UI ---> Event System . Esto creará un EventSystem si aún no existe. Si ya existe, Unity simplemente lo ignorará.


B. El componente UI o GameObject con el componente UI debe estar bajo unCanvas . Significa que unCanvas debe ser el padre del componente de la interfaz de usuario. Sin esto, EventSystem no funcionará y no se detectarán los clics.

Esto solo se aplica a los objetos de la interfaz de usuario. No se aplica a 2D (Sprite Renderer / cualquier 2D Collider) ni a Objetos 3D (Mesh Renderer / cualquier 3D Collider).


C. Si se trata de un objeto 3D, PhysicsRaycasterno está conectado a la cámara. Asegúrese de que PhysicsRaycasteresté conectado a la cámara. Consulte el n. ° 6 anterior para obtener más información.


D. Si se trata de un objeto 2D, Physics2DRaycasterno está conectado a la cámara. Asegúrese de que Physics2DRaycasteresté conectado a la cámara. Consulte el n. ° 7 anterior para obtener más información.


E. Si se trata de un objeto de interfaz de usuario que desea detectar clics con las funciones de la interfaz OnBeginDrag,OnPointerClick , OnPointerEntery otras funciones previstas en el # 1 a continuación el script con el código de detección debe adjuntar a ese objeto de interfaz de usuario que desea detectar haga clic en.


F .Además, si se trata de un objeto de interfaz de usuario en el que desea detectar clics, asegúrese de que no haya ningún otro objeto de interfaz de usuario frente a él. Si hay otra interfaz de usuario frente a la que desea detectar, bloqueará ese clic.

Para verificar que este no es el problema, deshabilite todos los objetos debajo del Lienzo excepto el que desea detectar, haga clic en y luego vea si hacer clic funciona.

Programador
fuente
1
La API de la interfaz de usuario está diseñada para funcionar tanto en dispositivos móviles como en computadoras de escritorio. Ese es el lado bueno de esto y esto no es un problema en absoluto. Actualizaré esto para incluir otro 3D (Mesh Renderer / Collider) y 2D (Sprite / 2D Collider) en un momento.
Programador
1
Se agregó Slider y 3D, ejemplo 2D. Esto es lo que debería usar ahora en el sistema de entrada o en las viejas formas de Raycast.
Programador
1
Eso es genial @Programmer. Esto es todo lo que necesito. Gracias :)
Dennis Liu
2
OnClick () no es una función de la interfaz. Probablemente quisiste decir OnPointerClickcuál usa la IPointerClickHandlerinterfaz. Por favor, lea mi respuesta nuevamente. Todo en mi respuesta debería funcionar en computadoras de escritorio y dispositivos móviles. He visto una respuesta que le dice a la gente que use OnPointerClickun componente de botón. Esto esta muy mal. Funcionará, pero hay un error que no conocen cuando lo haces. Para detectar cuándo se hace clic en un botón, use el evento en mi respuesta que usa AddListerner. No detecte el clic del botón OnPointerClick. OnPointerClickes para otros componentes que no es un botón.
Programador
1
Sería útil saber a qué objetos de juego adjuntar (o no adjuntar) estos scripts. Algunos son obvios (botón), pero ¿se supone que debo poner el número 1 en el objeto en el que quiero hacer clic? ¿En la Cámara? ¿El # 7 va en mi objeto de juego o en la cámara? ¿O está en otro lugar?
meed96
5

Puede agregar un EventTriggerComponenet a los elementos de su interfaz de usuario que ya los tienen Events, solo tiene que transmitir method/Functionun evento específico.

waqas ali
fuente
Gracias, creo que lo tengo.
Dennis Liu
5

También puede usar OnMouseDown. Se llama a OnMouseDown cuando el usuario ha presionado el botón del mouse mientras estaba sobre GUIElement o Collider. Este evento se envía a todos los scripts de Collider o GUIElement.

using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement; // The new load level needs this

public class ExampleClass : MonoBehaviour
{
    void OnMouseDown()
    {
        // Edit:
        // Application.LoadLevel("SomeLevel");
        // Application.LoadLevel() is depreciating but still works

         SceneManager.LoadScene("SomeLevel"); // The new way to load levels

    }
}
Jeffrey Lanters
fuente
0

hacer no utilizar OnMouseDown () para los problemas de rendimiento móvil y multi-touch.

Este código funciona en objetos de la interfaz de usuario para múltiples toques

En mi respuesta, uso el elemento Image con una etiqueta " Button " y tiene un script ButtonController con un método público ButtonDown () que se debe llamar cuando el usuario toca el elemento Image.

Nota : El elemento de imagen tiene un Colisionador 2D.

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

public class TouchScript : MonoBehaviour
{
    void Update()
    {
        PointerEventData pointer = new PointerEventData(EventSystem.current);
        List<RaycastResult> raycastResult = new List<RaycastResult>();

        foreach (Touch touch in Input.touches)
        {
            if(touch.phase.Equals(TouchPhase.Began))
            {
                pointer.position = touch.position;
                EventSystem.current.RaycastAll(pointer, raycastResult);

                foreach(RaycastResult result in raycastResult)
                {
                    if(result.gameObject.tag == "Button")
                    {
                        result.gameObject.GetComponent<ButtonController>().ButtonDown();
                    }              
                }
                raycastResult.Clear();
            }       
        }
    }
}
Mehmet Emin Yıldırım
fuente