Desenvolvemos um sistema para gerenciar eventos de clique na interface do Unity, capaz de distinguir entre cliques únicos, duplos e triplos. É importante notar que este componente deve ser anexado a um objeto com componente UI que possa receber eventos, não funcionando em objetos vazios.
using System;
using System.Collections;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
namespace UnityEngine.UI
{
public class GerenciadorCliques : MonoBehaviour, IPointerClickHandler
{
[Serializable]
public class EventoClique : UnityEvent
{
private int contadorAcoes = 0;
public int ContadorAcoes { get { return contadorAcoes + GetPersistentEventCount(); } }
public new void AddListener(UnityAction acao)
{
contadorAcoes++;
base.AddListener(acao);
}
public new void RemoveListener(UnityAction acao)
{
contadorAcoes--;
base.RemoveListener(acao);
}
}
[Tooltip("Intervalo de tempo máximo entre cliques para considerar como múltiplo clique")]
public float intervaloMaximo = 0.5f;
[SerializeField]
private EventoClique aoClicarUmaVez = new EventoClique();
public EventoClique AoClicarUmaVez { get { return aoClicarUmaVez; } }
[SerializeField]
private EventoClique aoClicarDuasVezes = new EventoClique();
public EventoClique AoClicarDuasVezes { get { return aoClicarDuasVezes; } }
[SerializeField]
private EventoClique aoClicarTresVezes = new EventoClique();
public EventoClique AoClicarTresVezes { get { return aoClicarTresVezes; } }
private bool processandoCliques = false;
private int numeroCliques = 0;
public void OnPointerClick(PointerEventData dadosEvento)
{
numeroCliques++;
if (!processandoCliques)
{
processandoCliques = true;
StartCoroutine(ProcessarCliques());
}
}
private IEnumerator ProcessarCliques()
{
bool temCliqueUnico = AoClicarUmaVez != null && AoClicarUmaVez.ContadorAcoes > 0;
bool temCliqueDuplo = AoClicarDuasVezes != null && AoClicarDuasVezes.ContadorAcoes > 0;
bool temCliqueTriplo = AoClicarTresVezes != null && AoClicarTresVezes.ContadorAcoes > 0;
if (temCliqueDuplo || temCliqueTriplo)
{
yield return new WaitForSeconds(intervaloMaximo);
}
if (numeroCliques == 1 && temCliqueUnico)
{
AoClicarUmaVez.Invoke();
}
else if (numeroCliques == 2)
{
if (temCliqueDuplo)
{
AoClicarDuasVezes.Invoke();
}
else if (temCliqueUnico)
{
AoClicarUmaVez.Invoke();
}
}
else if (numeroCliques >= 3)
{
if (temCliqueTriplo)
{
AoClicarTresVezes.Invoke();
}
else if (temCliqueDuplo)
{
AoClicarDuasVezes.Invoke();
}
else if (temCliqueUnico)
{
AoClicarUmaVez.Invoke();
}
}
numeroCliques = 0;
processandoCliques = false;
}
}
}
O uso deste componente pode ser feito tanto através da interface do Unity quanto programaticamente:
using UnityEngine;
public class ExemploUso : MonoBehaviour
{
public UnityEngine.UI.GerenciadorCliques gerenciadorCliques;
private void Awake()
{
if (gerenciadorCliques == null)
gerenciadorCliques = GetComponent<UnityEngine.UI.GerenciadorCliques>();
}
private void Start()
{
gerenciadorCliques.AoClicarUmaVez.AddListener(() =>
{
Debug.Log("Clique único detectado!");
});
gerenciadorCliques.AoClicarDuasVezes.AddListener(() =>
{
Debug.Log("Clique duplo detectado!");
});
gerenciadorCliques.AoClicarTresVezes.AddListener(() =>
{
Debug.Log("Clique triplo detectado!");
});
}
}
Para interações mais complexas como arrastar e soltar, o Unity oferece a classe UnityEngine.EventSystems.EventTrigger, que já possui implementações para divresos eventos:
public virtual void AoEntrar(PointerEventData dados)
public virtual void AoSair(PointerEventData dados)
public virtual void AoArrastar(PointerEventData dados)
public virtual void AoLargar(PointerEventData dados)
public virtual void AoPressionar(PointerEventData dados)
public virtual void AoLargarBotao(PointerEventData dados)
public virtual void AoClicar(PointerEventData dados)
public virtual void AoSelecionar(BaseEventData dados)
public virtual void AoDeselecionar(BaseEventData dados)
public virtual void AoRolar(PointerEventData dados)
public virtual void AoMover(AxisEventData dados)
public virtual void AoAtualizarSelecionado(BaseEventData dados)
public virtual void AoIniciarArrastoPotencial(PointerEventData dados)
public virtual void AoIniciarArrasto(PointerEventData dados)
public virtual void AoTerminarArrasto(PointerEventData dados)
public virtual void AoEnviar(BaseEventData dados)
public virtual void AoCancelar(BaseEventData dados)