O que estou tentando entender e aprender aqui é uma coisa muito básica: qual é a maneira mais geral e mais refinada de diferenciar adequadamente cliques únicos e cliques duplos dos três botões principais do mouse no Unity, usando C #?
Minha ênfase na palavra corretamente não é à toa. Embora eu tenha ficado surpreso que isso nunca tenha sido feito neste site, é claro que pesquisei e encontrei inúmeras perguntas semelhantes nos fóruns do Unity e nas próprias páginas de perguntas e respostas do Unity. No entanto, como geralmente ocorre com as respostas postadas nesses recursos, todas pareciam estar completamente erradas ou pelo menos um pouco amadoras.
Deixe-me explicar. As soluções propostas sempre tiveram uma das duas abordagens e suas falhas correspondentes:
- toda vez que um clique acontece, calcule o delta de tempo desde o último clique e, se fosse menor que um determinado limite, um clique duplo seria detectado. No entanto, essa solução resulta em que um clique rápido é detectado antes que o clique duplo seja detectado, o que é indesejável na maioria das situações, pois ativa ações de clique único e duplo.
Exemplo aproximado:
float dclick_threshold = 0.25f;
double timerdclick = 0;
if (Input.GetMouseButtonDown(0)
{
if (Time.time - timerdclick) > dclick_threshold)
{
Debug.Log("single click");
//call the SingleClick() function, not shown
} else {
Debug.Log("double click");
//call the DoubleClick() function, not shown
}
timerdclick = Time.time;
}
- defina um atraso de espera para o clique único a ser ativado, o que significa que, a cada clique, somente ative as ações de clique único se o tempo decorrido desde o último clique estiver acima de um determinado limite. No entanto, isso fornece resultados lentos, pois uma espera antes é possível notar a espera antes que os cliques únicos sejam detectados. Pior que isso, esse tipo de solução sofre discrepâncias entre as máquinas, pois não leva em conta a velocidade ou a velocidade lenta da configuração de velocidade do clique duplo do usuário no nível do sistema operacional.
Exemplo aproximado:
float one_click = false;
float dclick_threshold = 0.25f;
double timerdclick = 0;
if (one_click && ((Time.time - timerdclick) > dclick_threshold))
{
Debug.Log("single click");
//call the SingleClick() function, not shown
one_click = false;
}
if (Input.GetMouseButtonDown(0))
{
if (!one_click)
{
dclick = -1;
timerdclick = Time.time;
one_click = true;
}
else if (one_click && ((Time.time - timerdclick) < dclick_threshold))
{
Debug.Log("double click");
//call the DoubleClick() function, not shown
one_click = false;
}
}
Portanto, minhas perguntas se tornam as seguintes. Existe uma maneira mais refinada e confiável de detectar cliques duplos no Unity usando C #, além dessas soluções, e uma que lide com os problemas mencionados anteriormente?
Respostas:
As corotinas são divertidas:
fonte
Eu não sei ler ingles Mas o UniRx pode ajudá-lo.
https://github.com/neuecc/UniRx#introduction
fonte
Control Panel → Mouse
.O atraso padrão do clique duplo do Windows é 500ms = 0,5 segundos.
Geralmente em um jogo, é muito mais fácil lidar com o clique duplo no controle que está sendo clicado, não globalmente. Se você decidir lidar com cliques duplos globalmente, precisará implementar soluções alternativas para evitar dois efeitos colaterais muito indesejáveis:
Se você precisar usar uma implementação global, precisará verificar também o local do clique - se o mouse se mover muito longe, não será um clique duplo. Você normalmente implementaria um rastreador de foco que redefine o contador de clique duplo sempre que o foco muda.
Para a pergunta se você deve esperar até que o tempo limite do clique duplo passe, isso precisa ser tratado de maneira diferente para cada controle. Você tem 4 eventos diferentes:
Sempre que possível, você tenta projetar as interações da GUI para que o último evento não seja usado: O Windows File Explorer selecionará um item em um único clique imediatamente e o abrirá em um clique duplo e não fará nada em um único confirmado. clique.
Em outras palavras: Você usa as duas opções sugeridas, dependendo do comportamento desejado do controle.
fonte
As soluções acima funcionam para cliques feitos em toda a tela. Se você deseja detectar cliques duplos em botões individuais, achei que esta modificação da resposta acima está funcionando bem:
Anexe esse script a quantos botões desejar. Em seguida, na seção On Click do editor (para cada botão ao qual você anexa), clique em '+', adicione o botão a ele mesmo como objeto de jogo e selecione "DoubleClickTest -> startClick ()" como a função a ser chamada quando o botão é pressionado.
fonte
Eu estava procurando por um manipulador adequado de clique duplo. Eu encontrei este tópico e reuni algumas idéias realmente boas. Então, finalmente, eu vim com a seguinte solução e quero compartilhar com você. Espero que você ache este método útil.
Eu acho que é uma ótima abordagem usar o inspetor do Unity, porque dessa maneira o seu código é mais flexível, pois você pode fazer referência a qualquer um dos objetos do jogo visualmente e com segurança.
Primeiro adicione o componente Sistema de Eventos a qualquer um dos seus objetos de jogo. Isso também adicionará o componente Módulo de entrada independente . Isso cuidará dos eventos de entrada, como cliques e toques do mouse. Eu recomendo fazer isso em um objeto de jogo individual.
Em seguida, adicione o componente Trigger de eventos a qualquer objeto do jogo ativado por raycast . Como um elemento da interface do usuário ou um sprite, um objeto 3D com um colisor . Isso entregará o evento click ao nosso script. Adicione o tipo de evento Pointer Click e defina o objeto do jogo receptor que possui o componente de script Click Controller e, finalmente, selecione o método onClick () . (Além disso, você pode alterar o script para receber todos os cliques em uma atualização () e pular esta etapa.)
Portanto, o objeto do jogo receptor, que obviamente pode ser o acionador do evento, fará qualquer coisa com os eventos de clique único ou doudle.
Você pode definir o limite de tempo para o clique duplo, o botão desejado e os eventos personalizados para o clique único e duplo. A única limitação é que você pode escolher apenas um botão de cada vez para um objeto de jogo .
O script em si inicia uma rotina a cada primeiro clique com dois temporizadores. O firstClickTime e o currentTime em sincronia com o primeiro.
Essa corotina faz um loop uma vez no final de cada quadro até o prazo expirar. Enquanto isso, o método onClick () continua contando os cliques.
Quando o prazo expira, ele chama o evento de clique único ou duplo, de acordo com o clickCounter. Em seguida, ele define esse contador como zero, para que a corotina possa terminar e todo o processo comece do início.
fonte
Acho que não há como ler a mente do usuário, pois ele clicará simples ou duas vezes, afinal temos que aguardar a entrada. Embora você possa definir a espera de 0,01 segundos (o mínimo) para o segundo clique. A este respeito, eu iria para a opção de espera.
E SIM
Coroutines
são divertidos ...Uma alternativa
fonte