So erkennen Sie Klick- / Berührungsereignisse auf der Benutzeroberfläche und in GameObjects

79

Wie erkenne ich ein UI-Objekt auf Canvas on Touch in Android?

Zum Beispiel habe ich eine Leinwand , die 5 Objekte wie Image, RawImage, Buttons, InputFieldund so weiter.

Wenn ich das Button UI-Objekt berühre, dann mache ich etwas. Jede Schaltfläche führt beim Klicken unterschiedliche Vorgänge aus.

Der Code sieht folgendermaßen aus:

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

Wie geht das?

Zweitens: Wie erkennt man, dass Gameobject in Kontakt kommt? Ist es dasselbe mit dem oben genannten oder nicht?

Dennis Liu
quelle

Antworten:

165

Sie verwenden die Eingabe-API nicht für die neue Benutzeroberfläche. Sie abonnieren UI-Ereignisse oder implementieren je nach Ereignis eine Schnittstelle.

Dies sind die richtigen Methoden zum Erkennen von Ereignissen auf den neuen UI-Komponenten:

1 . Image, RawImageUnd TextKomponenten:

Implementieren Sie die benötigte Schnittstelle und überschreiben Sie deren Funktion. Das folgende Beispiel implementiert die am häufigsten verwendeten Ereignisse.

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

Sie verwenden Ereignisse, um sich für Schaltflächenklicks zu registrieren:

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

Wenn Sie etwas anderes als Button Click auf den Button erkennen, verwenden Sie Methode 1. Verwenden Sie beispielsweise Button down und nicht Button Click, verwenden Sie IPointerDownHandlerund seine OnPointerDownFunktion aus Methode 1.

3 . InputFieldKomponente:

Sie verwenden Ereignisse, um sich zu registrieren, um sich für InputField Submit zu registrieren:

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

So erkennen Sie, wann sich der Schiebereglerwert beim Ziehen ändert:

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

Verwenden Sie für andere Ereignisse Methode 1 .

5 . DropdownKomponente

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

}

NICHT-UI-OBJEKTE:

6. Für 3D-Objekte (Mesh Renderer / beliebiger 3D Collider)

In PhysicsRaycasterauf die Kamera dann verwenden Sie einen des Ereignisses von Methode 1 .

Der folgende Code wird automatisch PhysicsRaycasterzum Hauptcode hinzugefügt 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. Für 2D-Objekte (Sprite-Renderer / beliebiger 2D-Collider)

In Physics2DRaycasterauf die Kamera dann verwenden Sie einen des Ereignisses von Methode 1 .

Der folgende Code wird automatisch Physics2DRaycasterzum Hauptcode hinzugefügt 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
}

Fehlerbehebung beim EventSystem:

Auf der Benutzeroberfläche, 2D-Objekten (Sprite-Renderer / beliebiger 2D-Collider) und 3D-Objekten (Mesh-Renderer / beliebiger 3D-Collider) wurden keine Klicks festgestellt:

A .Überprüfen Sie, ob Sie über EventSystem verfügen. Ohne EventSystem können Klicks überhaupt nicht erkannt werden. Wenn Sie es nicht haben, erstellen Sie es selbst.


Gehen Sie zu GameObject ---> UI ---> Event System . Dadurch wird ein EventSystem erstellt, falls es noch nicht vorhanden ist. Wenn es bereits existiert, wird es von Unity einfach ignoriert.


B. Die UI-Komponente oder GameObject mit der UI-Komponente muss sich unter a befinden Canvas. Dies bedeutet, dass a Canvasdas übergeordnete Element der UI-Komponente sein muss. Ohne dies funktioniert EventSystem nicht und Klicks werden nicht erkannt.

Dies gilt nur für UI-Objekte. Dies gilt nicht für 2D-Objekte (Sprite-Renderer / 2D-Collider) oder 3D-Objekte (Mesh-Renderer / 3D-Collider).


C. Wenn dies ein 3D-Objekt ist, PhysicsRaycasterist es nicht an der Kamera angebracht. Stellen Sie sicher, dass diese PhysicsRaycasteran der Kamera angebracht ist. Siehe Nr. 6 oben für weitere Informationen.


D. Wenn dies ein 2D-Objekt ist, Physics2DRaycasterist es nicht an der Kamera angebracht. Stellen Sie sicher, dass diese Physics2DRaycasteran der Kamera angebracht ist. Siehe Nr. 7 oben für weitere Informationen.


E .Wenn dies ist ein UI - Objekt , das Sie wollen Klicks erkennen an den Schnittstellenfunktionen wie OnBeginDrag, OnPointerClick, OnPointerEnterund andere in den genannten Funktionen # 1 dann das Skript mit dem Erkennungscode muss an dieser UI - Objekt angebracht werden Sie klicken Sie ermitteln möchten.


F. Wenn es sich um ein UI-Objekt handelt, auf das Sie Klicks erkennen möchten, stellen Sie sicher, dass sich kein anderes UI-Objekt davor befindet. Wenn sich vor dem zu erkennenden Klick eine andere Benutzeroberfläche befindet, wird dieser Klick blockiert.

Um zu überprüfen, ob dies nicht das Problem ist, deaktivieren Sie jedes Objekt unter der Leinwand mit Ausnahme des Objekts, das Sie erkennen möchten. Klicken Sie auf und prüfen Sie, ob das Klicken funktioniert.

Programmierer
quelle
1
Die UI-API soll sowohl auf Mobilgeräten als auch auf Desktops funktionieren. Das ist die gute Seite davon und das ist überhaupt kein Problem. Ich werde dies in Kürze aktualisieren, um andere 3D (Mesh Renderer / Collider) und 2D (Sprite / 2D Collider) aufzunehmen.
Programmierer
1
Slider und 3D, 2D Beispiel hinzugefügt. Dies ist, was Sie jetzt verwenden sollten, wenn Sie das Eingabesystem oder die alten Raycast-Methoden verwenden.
Programmierer
1
Das ist großartig @Programmer. Das ist alles was ich brauche. Danke :)
Dennis Liu
2
OnClick () ist keine Funktion der Schnittstelle. Sie haben wahrscheinlich gemeint, OnPointerClickwelche die IPointerClickHandlerSchnittstelle verwendet. Bitte lesen Sie meine Antwort noch einmal. Alles in meiner Antwort sollte auf Desktop und Mobile funktionieren. Ich habe eine Antwort gesehen, die den Leuten sagt, dass sie OnPointerClickfür eine Button-Komponente verwenden sollen. Das ist so falsch. Es wird funktionieren, aber es gibt einen Fehler, von dem sie nicht wissen, wann Sie das tun. Verwenden Sie das Ereignis in meiner Antwort, um zu erkennen, wann auf eine Schaltfläche geklickt wird AddListerner. Knopfklick mit nicht erkennen OnPointerClick. OnPointerClickist für andere Komponenten, die kein Button ist.
Programmierer
1
Es wäre nützlich zu wissen, an welche Spielobjekte diese Skripte angehängt (oder nicht angehängt) werden sollen. Einige sind offensichtlich (Schaltfläche), aber soll ich # 1 auf das Objekt setzen, auf das ich klicken möchte? Auf der Kamera? Geht # 7 auf mein Spielobjekt oder die Kamera? Oder ist es woanders?
Meed96
5

Sie können EventTriggerIhren UI-Elementen, die diese bereits haben , eine Komponente hinzufügen , die EventsSie nur method/Functionan ein bestimmtes Ereignis weitergeben müssen.

waqas ali
quelle
Danke, ich denke, ich habe es verstanden.
Dennis Liu
5

Sie können auch OnMouseDown verwenden. OnMouseDown wird aufgerufen, wenn der Benutzer die Maustaste über dem GUIElement oder Collider gedrückt hat. Dieses Ereignis wird an alle Skripte des Colliders oder GUIElement gesendet.

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
quelle
0

Sie nicht verwenden OnMouseDown () für mobile Performance und Multi-Touch - Themen.

Dieser Code funktioniert auf UI-Objekten für Mehrfachberührungen

In meiner Antwort verwende ich das Image- Element mit einem " Button " -Tag und es verfügt über ein ButtonController- Skript mit einer öffentlichen ButtonDown () -Methode, die aufgerufen werden sollte, wenn der Benutzer das Image-Element berührt.

Hinweis : Das Bildelement verfügt über einen 2D-Collider.

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
quelle