I’m a big fan of local multiplayer – as far as I’m concerned, being bundled up with your mates cajoling each other and screaming at the TV is the very essence of gaming. I had an absolute blast at the recent Hugs ‘n Uppercuts local multiplayer event in Norwich, playing the likes of Gang Beasts, Nidhogg, Friendship Club etc.
Multiplayer games where players use joypads for input is easy – just connect additional USB/wireless controllers and away you go (AFAIK, Unity supports up to 11, which is a strange limit, but there you go…). But what about local multiplayer games where players use a mouse for input? I’m not aware of any such games, but I couldn’t think of a valid reason why not to try. Perhaps it’s simply the logistics of having enough surface space on which to operate the mice… or perhaps it’s because it turns out to be a bit of a technical challenge….
Connecting additional USB mice is, at first glance, just as easy as connecting additional USB joysticks. And Windows will recognise them just fine too. The problem is that every mouse will control the same, single cursor. And, if you ask Unity’s Input class for the mousePosition, or to GetMouseButtonDown(), you’ll get the response from all connected mice, with no way to distinguish them.
Recognising the mice separately requires hooking into the Raw Input events at the OS level. This needs a native (non-managed) plugin, so this solution is very much Windows-specific. There’s probably an equivalent for Mac/Linux, but who cares about those? Not me.
While researching this problem, I came across a few relevant projects:
- http://www.codeproject.com/Articles/17123/Using-Raw-Input-from-C-to-handle-multiple-keyboard – which handles multiple keyboards.
- http://forum.unity3d.com/threads/multiple-mice.1314/ – which apparently has the solution to multiple mice in Unity. Only it’s on the end of a broken 404 link 😦
- http://jstookey.com/arcade/rawmouse/ – which has a working C library to access multiple mice via Windows Raw Input, together with a C# port. The problem is it doesn’t work in Unity 5 because it relies on .NET libraries that aren’t supported by Unity’s Mono implementation, and also because it’s 32bit only, and my Unity Editor runs in 64bit mode.
So, I rolled my sleeves up and hacked together various bits of the above into a Frankenstein-ish solution. It supports both 32/64 bit and will work in the editor and in a standalone build, though not a web build. To capture the mouse input, the program needs to create a window handle via System.Forms. Unity doesn’t really support System.Forms, and it will throw some warnings in the Editor (not in a build though), but it will (should) work just fine after that. Tested with up to 4 mice on Windows 8.1 64 bit and it works fine.
To use, you need to copy both the following dlls into the /Plugins directory of your project.
- https://dl.dropboxusercontent.com/u/148583170/MultiMice/RawInputSharp.dll
- https://dl.dropboxusercontent.com/u/148583170/MultiMice/RawMouseDriver.dll
And the following script shows basic usage to access 4 mice:
using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using RawMouseDriver; using RawInputSharp; public class MouseInput : MonoBehaviour { RawMouseDriver.RawMouseDriver mousedriver; private RawMouse[] mice; private Vector2[] move; private const int NUM_MICE = 4; // Use this for initialization void Start () { mousedriver = new RawMouseDriver.RawMouseDriver (); mice = new RawMouse[NUM_MICE]; move = new Vector2[NUM_MICE]; } void Update() { // Loop through all the connected mice for(int i=0; i<mice.Length; i++){ try { mousedriver.GetMouse(i, ref mice[i]); // Cumulative movement move[i] += new Vector2(mice[i].XDelta, -mice[i].YDelta); } catch { } } } void OnGUI(){ GUILayout.Label("Connected Mice:"); for(int i=0; i< mice.Length; i++){ if(mice[i] != null) GUILayout.Label("Mouse[" + i.ToString() + "] : " + move[i] + mice[i].Buttons[0] + mice[i].Buttons[1]); } } void OnApplicationQuit() { // Clean up mousedriver.Dispose (); } }
And here it is in action:
Great work, Ali!
I did a unity port of Ryan C. Gordon’s ManyMouse a while back (https://icculus.org/manymouse/).
Got it just barely working. I think Brendon Chung wanted to use it so I packaged it up for him. Haven’t tried to gussy it up at all, so use at your own risk, but it is Mac/Lunix/Windows compatible:
https://drive.google.com/file/d/0BzlnW3oVU52falI3a3ByZU15N2M/view?usp=sharing
Probably not a pretty implementation, but I do believe I got it working, yeah.
Also, what’s happening with your GetMouse call? Is the dll accumulating input delta until it’s called in a unity update? Just wondering because I’m obsessive about polling rates.
I tried to use it, but it’s causing an Internal compiler error.
Message was: “Internal compiler error. See the console log for more information. output was:
Unhandled Exception: System.TypeLoadException: Could not load type ‘RawMouseDriver.RawMouseDriver’ from assembly ‘RawMouseDriver, Version=1.0.5660.39238, Culture=neutral, PublicKeyToken=null’.”
which Unity version do i have to use?