Input: Missing mouse button events

I’m trying to create an input system that will catch all left mouse button events.

With the current code I’m missing about 1 in every 35 left mouse button events.

The target platform is a Windows Standalone created in Windows 5 Pro running on a machine with Windows 10. The mouse input is being driven by launching toy ammunition at a touchscreen, at a rate of about 2-ish per second. I’m testing on a scene with no real overhead, just a plane and instantiating a sphere locked at 60 frames per second with vsync. My code is using OnGUI to put mouse events into a queue and Update to process them. I’ve tried the popular TouchScript and Rewired plug-ins and the result is similar.

Any advice would be greatly appreciated.

import System.Collections.Generic;

var queue = new List.<Event>();  
var currentEvent: Event;
var mouseNumber: int;
var mouseTextBox: GameObject;
var mouseSphere: GameObject;
var mouseVisibleNumber : int; 


function OnGUI() {
  	    currentEvent = Event.current;   
           //find left mouse button clicks
            if (currentEvent.type == EventType.MouseDown && currentEvent.button == 0){
                      //adds to back of queue
                      queue.Add(currentEvent);
                      } 
}
     
     
function Update() {
     var hit: RaycastHit;
      //if the queue has anything in it
      if (queue.Count > 0){
      	 //references front of queue   
       	 var processingEvent = queue [0];
       	 var flippingEvent = processingEvent.mousePosition;   
       	 //flips y coordinate, as putting it in the queue causes it to be inverted somehow
       	 var flippingY = Screen.height-processingEvent.mousePosition.y;
       	 var ray = Camera.main.ScreenPointToRay(Vector3(processingEvent.mousePosition.x, flippingY, 0));
       					//if the mouseclick hits something, add number to textbox            
                 		if (Physics.Raycast(ray, hit)){
                 			mouseNumber ++;   
                 			Instantiate (mouseSphere, hit.point, transform.rotation);
                 			mouseVisibleNumber ++;
                 		    var mouseInt = mouseVisibleNumber; 
                 	    	var mouseStr = mouseInt.ToString();
                 	    	mouseTextBox.GetComponent(UI.Text).text = mouseStr;
                 	    		for (var queuedEvents in queue){
                 	    		Debug.Log (queue.Count + "," + queuedEvents);
                 	    		}  	
							queue.RemoveAt(0);
							}
							}
							}

Do you have Mouse buttons in Edit>Project Settings>Input ? Mouse buttons are called “Fire1” and “Fire2”.

60 frames per second with vsync

Disable v-sync and see what happens.

Unity input and Rewired are single-threaded. Mouse messages are delivered to that thread at the beginning of every update. If mouse messages are received in the middle of the frame, Windows will only deliver the last message.

The mouse generates an input event when the user moves the mouse, or presses or releases a mouse button. The system converts mouse input events into messages and posts them to the appropriate thread’s message queue. When mouse messages are posted faster than a thread can process them, the system discards all but the most recent mouse message.

If you’re updating at 60 fps and your click lasts for 0.005s (1/3 of a frame, which is likely since you’re shooting an object at a screen), the last mouse event Windows will deliver will be mouse UP, not down. That means you miss the click event.

One way to be sure to catch all those events would be to update input at a much higher rate. The easiest way would be to disable v-sync. A better way would be to have input update on a separate thread so the refresh rate is much higher than 60hz and buffer click events.

If you have any control over the data produced by the touchscreen, you could tweak that so it lasts at least 1/30th of a second or so.