- Home /
How to map multiple different types of controllers at the same time
Hi everyone.
I want to make it so I have support for both: my keyboard, my xbox controller, my dualshock 4 and any other controller I might want to ad in the future.
I tried to just add the button mappings to Unity's input list but I found out that it read some dualshock inputs as inputs from the xbox controller.
That won't do becouse it will mess up my controls when I try to use ether one.
I want it to reconise every controller automatically when I press a button and don't want to have to switch it in the menu.
I know there are plugins for this, but I want to do my project without them.
So does anyone know how I can map this in Unity?
PS: I already have some code that I wanted to use as an input combiner but I probably have to rewrite everything once I have the solution, also it's not finished because I stopped writing when I realised that dualshock 4 used some of the xbox controllers inputs.
Here is my code:
using UnityEngine;
using System.Collections;
public class ControlMapper : MonoBehaviour {
//*Camera inputs*
private float camXinput = 0.0f;
private float camYinput = 0.0f;
//Keyboard and mouse
private float mouseXinput = 0.0f;
private float mouseYinput = 0.0f;
//Dualshock 4
private float DS4JoyRXinput = 0.0f;
private float DS4JoyRYinput = 0.0f;
//Windows/XBOX controller
private float XBOXYoyRXinput = 0.0f;
private float XBOXYoyRYinput = 0.0f;
//*Move inputs*
private float moveXinput = 0;
private float moveYinput = 0;
//Keyboard and mouse
private float ADKeyXinput = 0;
private float WSKeyYinput = 0;
//Dualshock 4
private float DS4JoyLXinput = 0;
private float DS4JoyLYinput = 0;
//Windows/XBOX controller
private float XBOXYoyLXinput = 0.0f;
private float XBOXYoyLYinput = 0.0f;
//*Jump inputs*
private bool jumpInputPress = false;
private bool jumpInputHold = false;
private bool jumpInputRelease = false;
//Keyboard and mouse
private bool spaceInputPress = false;
private bool spaceInputHold = false;
private bool spaceInputRelease = false;
//Dualshock 4
private bool DS4CrossInputPress = false;
private bool DS4CrossInputHold = false;
private bool DS4CrossInputRelease = false;
//Windows/XBOX controller
private bool XBOXAInputPress = false;
private bool XBOXAInputHold = false;
private bool XBOXAInputRelease = false;
void Update ()
{
//*Find camera inputs*
//Find mouse inputs
mouseXinput = Input.GetAxis("Mouse X");
mouseYinput = Input.GetAxis("Mouse Y");
//Find DS4JoyR inputs
DS4JoyRXinput = Input.GetAxis("DS4JoyRX");
DS4JoyRYinput = Input.GetAxis("DS4JoyRY");
//Find XBOXJoyR inputs
//*Find move inputs*
//Find mouse inputs
ADKeyXinput = Input.GetAxis("ADKey's X");
WSKeyYinput = Input.GetAxis("WSKey's Y");
//Find DS4JoyL inputs
DS4JoyLXinput = Input.GetAxis("DS4JoyLX");
DS4JoyLYinput = Input.GetAxis("DS4JoyLY");
}
}
Also can somebody please tell me how to enter white spaces in this forum? I always have put in 2 enters to make a new line and adding more new lines doesn't work either.
I haven't been able to figure out white spaces either. $$anonymous$$ind of annoying... $$anonymous$$akes everything much more cluttered. About the best we have as far as I know is breaking our text up with code snippets or using the "Horizontal Rule".
Like this.
Oh that's a shame.
Thanks anyway.
PS: What is Horizontal Rule?
Answer by Stratosome · Jul 16, 2018 at 07:35 AM
Hah, I'll give an attempt at an explanation to what I've done in the past but I don't know if I've got code to provide. So, here's what I did: whenever you plug in a controller, getjoysticknames() is updated and shows a new joystick name in the array. After gathering the names that Unity uses for the different controllers (by looking at the getjoysticknames array), I made scriptable objects that have stored mappings for different controllers. So, one of the scriptableobjects might have a name variable being "joycon" with the proper mappings for the cute little controller. After having the set of scriptableobjects, one for each controller type, I then dumped those scriptableobjects into a custom script of mine and asked it to generate a bunch of inputs for every one of those controllers. So, THE SCRIPT would add to Unity's input manager list. One of them might be like 1 joycon A_Button (something more complex than that, but that's the idea). So, I used the script to populate Unity's input manager with all of these different controller types. I then made a controller manager script that would detect which controller is plugged in using the getjoysticknames array, and then look up the correct mappings in the input manager to reference for in-game controls.
Sorry, about the best I can give is the explanation. For the controller manager script, I slightly referenced this YouTube video. Maybe this will give you some ideas or something.
That sounds like it could work.
So first I have to use "getjoysticknames()" somewhere, to get the names of the inputs?
(Where should I use this command to get the quickest result?)
And then I have to make scriptable objects? (I am not yet familiar with these things or what they do. I will look it up)
And then make a script to implant this into Unity's input manager list.
And when all thats done I can make what I wanted to make in the first place. (A input manager script to recognize and combine the correct inputs into the inputs used for my game)
I hope I understud you right and I will also look at the video.
Edit: Oh I know this video, still gonna watch again. :)
Thanks for the response. :)
Yeah, pretty much. This took me a good week to do back when I did it, so it would probably be difficult to try to make, but it's certainly doable. This was also just my way of getting this to work. It's POSSIBLE that there are other simple ways to do this, but if this works, it's a really neat way to add new controller schemes and such. To figure out what the controllers are called in Unity, you can use this simple little script I made for ya:
using UnityEngine;
[ExecuteInEdit$$anonymous$$ode]
public class ShowConnectedControllers : $$anonymous$$onoBehaviour {
public string[] controllers;
void Update () {
controllers = Input.GetJoystickNames();
}
}
Actually, if you don't need multiple players, or anything very complex, and you just need to detect and use different control schemes for the different controller types, it would probably be best to avoid the scriptableobjects and using code to write to the input manager. That would just be a bunch of extra work (cool work, but extra). The main work then for you would just be making the controller manager script to detect the connected controller type (by name from GetJoystickNames), and then typing in all of the various inputs into the input manager yourself. You will have to type them in a specific way though. Something like this:
XBOX360 R Horizontal
XBOX360 R Vertical
...
PS4 R Horizontal
PS4 R Vertical
...
Your controller manager script then would then attach on the detected controller type to the front of the requested input to grab one of the inputs in the input manager list.
Yeah, this way might be the better way of doing it. Learning how to use ScriptableObjects for this and writing to Unity's input manager can take a bit of time to learn.
Well whatever works.
But I do want it to work with split screen and drop in drop out in the future.
Can it do that?
Also somewhere you say that you just change the controls based on which controller is active.
I don't think I can do that, becouse I will add split screen and drop in drop out in the future.
So I wanna be able to plug in and plug out different controllers while the game is running and recognize which is which player at the same time.
Answer by Magic-4e · Jul 18, 2018 at 09:33 AM
Ok someone gave me a good perspective of controller mapping, but can someone tell me if his advice works with local multiplayer and swamping controllers real time?
Does it work with local multiplayer and realtime controller swamping?
Sorry, I am still learning.
And the better I can piece these things together the better I can get a clear head.
@$$anonymous$$agic-4e
Hah, don't be sorry. I apologize for not answering sooner. I forgot to check this earlier. Short answer to that question there: We can make it work for multiplayer and controller swapping! What I described above was kind of for a single controller thing, but yeah, below I explain kind of how you could go about handling these things.
Um, alrighty, here's the deal with multiplayer stuffs. I managed to get multiplayer and controller adding and dropping working pretty well with that big long method with the fancy stuff that I originally said with scriptableobjects and writing to Unity's input manager. It's hard though. Unity's controller management stuff could (and maybe should) be easier to work with. This might be kind of a long response, so hopefully it doesn't get too messy. I'll try to break it up into sections.
$$anonymous$$ULTIPLE PLAYERS
So, when setting up input in Unity's input manager, inside of one of the input things, you can select the "Joy Num". That is used to only let controllers that are in that "position" use that input (hopefully that makes sense). The default is "Get $$anonymous$$otion From All Joysticks" I think. This obviously would cause problems for multiplayer games. So, one trick to do it, is while creating the input manager list (either in code or manually), you can perhaps throw a number in front of the input name to represent an input for a specific controller while also assigning that "Joy Num" variable to the proper number. Here is what my input manager now kind of looks like (it wouldn't let me upload an image for some reason :c):
(size = 260)
1 PS4_Windows R Joystick Horizontal
1 PS4_Windows R Joystick Vertical
1 PS4_Windows L Joystick Horizontal
...
2 PS4_Windows R Joystick Horizontal
2 PS4_Windows R Joystick Vertical
...
1 Joycon_Windows A Button
1 Joycon_Windows B Button
1 Joycon_Windows X Button
...
A inputs for each type of controller (PS4, Joycon, XBOX360), on each player number (1-4), on each platform (windows). So, with this massive amount of inputs now, if your controller manager script or whatever, you just have to detect the connected controller's position (player number) and the type of controller. With that info, you can build a string ("1 PS4_Windows R Joystick Vertical") and send it to the input manager to receive input.
ADDING / DROPPING
Alright, this part is kind of complicated. When a controller is unplugged while playing in Unity, that little spot in the GetJoystickNames() array doesn't disappear. It'll stay there as an empty "controller". If you plug in the controller again (to the same USB port) it will fill that spot again. If you reconnect the controller to a different USB port, it is considered a new controller. Which is blah, but I guess it might kind of make sense. So, to check for newly connected controllers (or disconnected controllers), what I did was have a function that is called like every 0.2 seconds to get the GetJoystickNames() array, and compare it with the last version of the array. If a spot is now empty and it wasn't before, that controller disconnected. If it is now populated and wasn't there before, yay, new controller (or potentially reconnected controller).
It is kind of hard to keep track of who is considered 1st player or 2nd player though since you can't just rely on the position in the GetJoystickNames() array. What I did was when a new controller was connected (found using that function called every 0.2 or so seconds), I assigned a controller number to it (I made a class to hold a controllers data like the type of controller and its "position" like 1st, 2nd, so on). If that controller is found to have been disconnected, the previous controllers still retain their position, and there are now gaps in the ordering of controllers. So, for example, let's say we have controllers 1, 2, and 3 plugged in. If player 2 disconnects, there is a gap: 1, _, and 3. Any new controllers that are plugged in at this point will then fill that gap or start increasing the player number (4, 5, ...). I'd suggest using delegates inside of the one function (that is called every 0.2 seconds blah blah). This would make it extremely easy to add controller connect or disconnect events.
Yep, that's what I've got for now unless you have further questions. Also, I certainly can't guarantee that this is the best way to do it. I just thought of this one night and it sounded pretty decent, so I went along with it. And finally, sorry if my stuff explanations are confusing hah. Doing the best I can. :P
Thanks for the response and sorry for my late one.
I see where you are going with this.
So I somehow need to tell unity which usb port and which type of controller is used for a player.
I think I need some time too take this all in it's a lot. XD
BTW I think the best way to keep track of the players is by saying:
If a new controller is plugged in, a new player is registered.
If a controller with a player assigned gets unplugged, then the game will ask to reconnect a controller of any type and press a button to assign a new controller to the recent disconnected player or the main player will press the start/escape button (for example) to kick that player and continue.
I could let the gap be because it might get confusing when the player numbers get switched up. Other wise I could just delet the gap when a player is kickt.
But thats just my idea.
Anyway thanks for the info I will accept your awnser when I get it right.
($$anonymous$$ight take a while sorry :-\ )
Yeah, that's what I was thinking about the gap. I leave it there (at least during the game) because we probably wouldn't want to have player 3 become player 2 suddenly while the game is playing. The asking to reconnect is a good idea. Not something I had coded in yet. Perhaps I'll want to revisit my code and look into that. :P
Also, as for the "tell unity which usb port" part, I don't think there is really a way to do that? All I've managed to get is if a controller is plugged into the same spot that it was. So, here's a little explanation of what I found. If you plug in an Xbox360 controller (for example) into USB port 1 (I'm just giving it a number because), it'll show up as a new controller in the GetJoystickNames() array. You you unplug it, it will be an empty spot. If you plug it into a USB port 2, there will be a new array element with that controller's name and the first one will still be empty but there. If you unplug that same controller and plug it back into USB port 1, it will make that first array element that controller now and the second element is now empty. If you plug a NEW controller (whatever kind) into USB port 2, it ISN'T going to fill array element 2. It is going to be a new element in the array. It's kinda frustrating to work with, but it is like JUST ENOUGH info to kind of get all of this working hah.
Don't be sorry if it takes a while. Took me a while to do all of it. I'll check this every now and then to see if you have further questions about the way I did it here. Or if you just wanna open up new questions about specifics, I'll keep an eye out for those too. ;)