Как заменить OnMouseDown в новой системе ввода Unity?

#unity3d

#unity3d

Вопрос:

В Unity появилась новая система ввода, в которой старая OnMouseDown() {} больше не работает.

В руководстве по миграции упоминается замена этого на Mouse.current.leftButton.isPressed . И в других сообщениях на форуме они упоминают использование InputAction . Проблема в том, что эти параметры обнаруживают щелчки мыши в любом месте в сцене, а не только на объекте:

 public InputAction clickAction;

void Awake() {
      clickAction.performed  = ctx => OnClickedTest();
}

void OnClickedTest(){
      Debug.Log("You clicked anywhere on the screen!");
}

// this doesn't work anymore in the new system
void OnMouseDown(){
      Debug.Log("You clicked on this specific object!");
}
  

Как я могу обнаружить щелчки мыши по определенному игровому объекту с новой системой ввода в Unity?

Ответ №1:

С помощью этого кода где-нибудь в вашей сцене:

 using UnityEngine.InputSystem;
using UnityEngine;

public class MouseClicks : MonoBehaviour
{
    [SerializeField]
    private Camera gameCamera; 
    private InputAction click;

    void Awake() 
    {
        click = new InputAction(binding: "<Mouse>/leftButton");
        click.performed  = ctx => {
            RaycastHit hit; 
            Vector3 coor = Mouse.current.position.ReadValue();
            if (Physics.Raycast(gameCamera.ScreenPointToRay(coor), out hit)) 
            {
                hit.collider.GetComponent<IClickable>()?.OnClick();
            }
        };
        click.Enable();
    }
}
  

Вы можете добавить IClickable интерфейс ко всем игровым объектам, которые хотят реагировать на клики:

 public interface IClickable
{
    void OnClick();
}
  

и

 using UnityEngine;

public class ClickableObject : MonoBehaviour, IClickable
{
    public void OnClick() 
    {
        Debug.Log("somebody clicked me");
    }
}
  

Комментарии:

1. Для этого все еще требуется объект. Что, если вам нужно определить, был ли щелчок в любом месте экрана? Допустим, у вас есть контекстное меню, появляющееся прямо рядом с курсором, которое появляется, когда пользователь нажимает на что-то. Кажется, что это невероятно распространенная и тривиальная вещь в игре. Но теперь нет способа заставить его исчезнуть, если пользователь нажимает в любом месте экрана. И если мы взломаем гигантскую невидимую кнопку позади меню, это означает, что другие элементы пользовательского интерфейса не будут доступны для просмотра, пока меню активно.

2. Очень полезно, спасибо

Ответ №2:

Убедитесь, что у вас есть EventSystem с InputSystemUIInputModule в сцене и PhysicsRaycaster или Physics2DRaycaster на вашем Camera , а затем используйте IPointerClickHandler интерфейс объекта с коллайдером для самого объекта или его дочерних элементов:

  using UnityEngine;
 using UnityEngine.EventSystems;
 public class MyClass : MonoBehaviour, IPointerClickHandler {
    public void OnPointerClick (PointerEventData eventData)
    {
        Debug.Log ("clicked");
    }
 }
  

Комментарии:

1. Но это не новая система ввода. EventSystems из пакета пользовательского интерфейса Unity.

2. Что такое «объект»? Мне нужно иметь возможность определять, был ли нажат щелчок в любом месте экрана. Я реализую контекстное меню, которое появляется рядом с курсором пользователя (например, при щелчке правой кнопкой мыши в Windows или Mac). Если они щелкнут в любом месте, оно должно исчезнуть. Я мог бы сделать «объект» гигантской невидимой кнопкой, которая появляется прямо за меню. Но учтите это: теперь другие элементы пользовательского интерфейса не будут получать событие click. Если пользователь хотел щелкнуть по одному из них, пока меню было активным, оно не будет работать для этого щелчка.

3. @Peyotle — InputSystemUIInputModule на самом деле из новой системы ввода. Да, EventSystem это из пакета пользовательского интерфейса, как есть PhysicsRaycaster : в пакете пользовательского интерфейса есть решение, поставляемое Unity, для того, что Коля делает вручную. Новая система ввода является заменой для UnityEngine.Input , а не для пакета пользовательского интерфейса. @pete — Это то, с чем уже был решен исходный вопрос Mouse.current.leftButton.isPressed — на самом деле вопрос заключался в щелчке по объекту.