UI 및 게임 오브젝트에서 클릭 / 터치 이벤트를 감지하는 방법


83

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가 터치를 감지하는 방법은 무엇입니까? 위와 동일합니까?

답변:


172

새 UI에 입력 API를 사용하지 않습니다. UI 이벤트를 구독하거나 이벤트에 따라 인터페이스를 구현합니다.

다음은 새 UI 구성 요소에서 이벤트를 감지하는 적절한 방법입니다.

1 . Image, RawImageText구성 요소 :

필요한 인터페이스를 구현하고 해당 기능을 재정의합니다. 아래 예는 가장 많이 사용되는 이벤트를 구현합니다.

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

다른 이벤트의 경우 방법 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 충돌체)

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 오브젝트 용 (스프라이트 렌더러 / 모든 2D 충돌체)

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
}

EventSystem 문제 해결 :

UI, 2D 개체 (Sprite Renderer / 모든 2D Collider) 및 3D 개체 (Mesh Renderer / 모든 3D Collider)에서 클릭이 감지되지 않았습니다.

A. EventSystem이 있는지 확인하십시오. EventSystem이 없으면 클릭을 전혀 감지 할 수 없습니다. 가지고 있지 않다면 직접 만드십시오.


로 이동하여 게임 오브젝트 ---> UI ---> 이벤트 시스템 . 아직 존재하지 않는 경우 EventSystem이 생성됩니다. 이미 존재하는 경우 Unity는이를 무시합니다.


B. UI 구성 요소 또는 UI 구성 요소가있는 GameObject는 Canvas. 이는 a Canvas가 UI 구성 요소의 부모 여야 함을 의미합니다 . 이것이 없으면 EventSystem이 작동하지 않고 클릭이 감지되지 않습니다.

이는 UI 개체에만 적용됩니다. 그것은 하지 않습니다 2D (스프 렌더 / 모든 2D 충돌 장치) 또는 3D 개체 (메쉬 렌더러 / 어떤 3D 충돌 장치)에 적용됩니다.


C. 3D 개체 인 PhysicsRaycaster경우 카메라에 부착되지 않습니다. 그것이 PhysicsRaycaster카메라에 부착되어 있는지 확인하십시오 . 자세한 내용은 위의 # 6 을 참조하십시오.


D. 2D Object 인 Physics2DRaycaster경우 카메라에 부착되지 않습니다. 그것이 Physics2DRaycaster카메라에 부착되어 있는지 확인하십시오 . 자세한 내용은 위의 # 7 을 참조하십시오.


E .If이는 인터페이스 등의 기능에 대한 클릭을 감지하고자하는 UI 객체 인 OnBeginDrag, OnPointerClick, OnPointerEnter과에 언급 된 다른 기능 # 1 다음 검출 코드 스크립트가이 UI 개체에 연결해야합니다 당신이 클릭 감지합니다.


F. 또한 이것이 클릭을 감지하려는 UI 객체 인 경우 앞에 다른 UI 객체가 없는지 확인합니다. 클릭을 감지하려는 UI 앞에 다른 UI가 있으면 해당 클릭을 차단합니다.

이것이 문제가 아닌지 확인하려면 클릭을 감지하려는 개체를 제외한 캔버스 아래의 모든 개체를 비활성화 한 다음 클릭이 작동하는지 확인합니다.


1
UI API는 모바일과 데스크톱 모두에서 작동합니다. 그것은 그것의 좋은면이고 이것은 전혀 문제가되지 않습니다. 잠시 후에 다른 3D (Mesh Renderer / Collider)와 2D (Sprite / 2D Collider)를 포함하도록 업데이트하겠습니다.
프로그래머

1
Slider 및 3D, 2D 예제가 추가되었습니다. 이것은 입력 시스템 또는 이전 Raycast 방식을 사용하여 지금 사용해야하는 것입니다.
프로그래머

1
훌륭한 @Programmer입니다. 이것이 내가 필요한 전부입니다. 감사합니다 :)
데니스 리우

2
OnClick ()은 인터페이스의 함수가 아닙니다. 인터페이스 OnPointerClick를 사용하는 것을 의미했을 것입니다 IPointerClickHandler. 내 대답을 다시 읽으십시오. 내 대답의 모든 것은 데스크톱과 모바일에서 작동해야합니다. 사람들에게 OnPointerClickButton 구성 요소 를 사용하도록 지시하는 답변을 보았습니다 . 이것은 너무 잘못되었습니다. 그것은 작동하지만 당신이 그것을 할 때 그들이 알지 못하는 버그가 있습니다. 버튼이 클릭 될 때를 감지하려면을 사용하는 내 대답의 이벤트를 사용하십시오 AddListerner. 로 버튼 클릭을 감지하지 마십시오 OnPointerClick. OnPointerClick버튼이 아닌 다른 구성 요소를위한 것입니다.
프로그래머

1
이 스크립트를 첨부하거나 첨부하지 않을 게임 오브젝트가 무엇인지 아는 것이 유용 할 것입니다. 일부는 분명하지만 (버튼) 클릭하려는 개체에 # 1을 입력해야합니까? 카메라에서? # 7은 내 게임 오브젝트 나 카메라에 있습니까? 아니면 다른 곳에 있습니까?
meed96

5

특정 이벤트 를 전달하기 만하면 EventTrigger이미 이러한 요소가있는 UI 요소에 Componenet을 추가 할 수 있습니다 .Eventsmethod/Function


감사합니다.
Dennis Liu

5

OnMouseDown도 사용할 수 있습니다. OnMouseDown은 사용자가 GUIElement 또는 Collider 위에있는 동안 마우스 버튼을 눌렀을 때 호출됩니다. 이 이벤트는 Collider 또는 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

    }
}

0

되지 모바일 성능과 멀티 터치 문제에 대한 ()하면 onMouseDown 사용합니다.

이 코드는 멀티 터치 용 UI 개체에서 작동합니다.

내 대답에서는 " Button "태그와 함께 Image 요소를 사용 하고 사용자가 Image 요소를 터치 할 때 호출되어야 하는 ButtonDown () 공용 메서드 가있는 ButtonController 스크립트 가 있습니다.

참고 : 이미지 요소에는 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();
            }       
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.