Как обнаружить события нажатия / касания в интерфейсе пользователя и GameObjects
Как обнаружить объект пользовательского интерфейса на холсте на Touch в Android?
Например, у меня есть холст, который имеет 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? Это то же самое с выше или нет?
3 ответа
Вы не используете API ввода для нового пользовательского интерфейса. Вы подписываетесь на события пользовательского интерфейса или реализуете интерфейс в зависимости от события.
Вот правильные способы обнаружения событий в новых компонентах пользовательского интерфейса:
1 Image
, RawImage
а также 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); });
}
Для других событий используйте метод 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)
{
}
НЕОБЪЕКТНЫЕ ОБЪЕКТЫ:
6.Для 3D-объектов (Mesh Renderer/ любой 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-объекта (Sprite Renderer/ любой 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:
Не обнаружено щелчков на интерфейсе пользователя, 2D-объектах (Sprite Renderer/ любой 2D-коллайдер) и 3D-объектах (Mesh Renderer/ любой 3D-коллайдер):
. Проверьте, что у вас есть EventSystem. Без EventSystem он не может обнаружить щелчки вообще. Если у вас его нет, создайте его сами.
Перейдите в GameObject ---> UI ---> Система событий. Это создаст EventSystem, если она еще не существует. Если он уже существует, Unity просто проигнорирует это.
Б. Компонент пользовательского интерфейса или GameObject с компонентом пользовательского интерфейса должен находиться под Canvas
, Это означает, что Canvas
должен быть родителем компонента пользовательского интерфейса. Без этого EventSystem не будет работать и щелчки не будут обнаружены.
Это относится только к объектам пользовательского интерфейса. Это не относится к 2D (Sprite Renderer/ любой 2D-коллайдер) или 3D-объектам (Mesh Renderer/ любой 3D-коллайдер).
C. Если это 3D-объект, PhysicsRaycaster
не прикреплен к камере. Удостоверься что PhysicsRaycaster
прикреплен к камере. См. № 6 выше для получения дополнительной информации.
D. Если это 2D объект, Physics2DRaycaster
не прикреплен к камере. Удостоверься что Physics2DRaycaster
прикреплен к камере. См. № 7 выше для получения дополнительной информации.
E. Если это объект пользовательского интерфейса, на котором вы хотите обнаружить щелчки с помощью функций интерфейса, таких как OnBeginDrag
, OnPointerClick
, OnPointerEnter
и другие функции, упомянутые в #1, затем сценарий с кодом обнаружения должен быть присоединен к тому объекту пользовательского интерфейса, на котором вы хотите обнаружить щелчок.
Кроме того, если это объект пользовательского интерфейса, на котором вы хотите обнаруживать щелчки, убедитесь, что перед ним нет другого объекта пользовательского интерфейса. Если перед тем, который вы хотите обнаружить, есть другой пользовательский интерфейс, он будет блокировать этот щелчок.
Чтобы убедиться, что это не проблема, отключите каждый объект в Canvas, кроме того, который вы хотите обнаружить, щелкните, затем посмотрите, работает ли щелчок.
Вы можете добавить EventTrigger
Componenet для ваших элементов пользовательского интерфейса, которые уже имеют эти Events
тебе просто нужно пройти method/Function
на конкретное событие.
Вы также можете использовать OnMouseDown. OnMouseDown вызывается, когда пользователь нажимает кнопку мыши, находясь над элементом GUIElement или 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
}
}
Как не использовать OnMouseDown() по вопросам мобильной производительности и мультитач.
Этот код работает с объектами пользовательского интерфейса для множественных касаний
В своем ответе я использую элемент Image с тегом "Button", и у него есть сценарий ButtonController с общедоступным методом ButtonDown(), который должен вызываться, когда пользователь касается элемента Image.
Примечание: элемент изображения имеет 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();
}
}
}
}