Hi, I'm using the latest Input System implementation (from github/develop). I've set up an Input Action Asset, and I'm attaching my actions through this: Code (CSharp): _input.GamePlay.Move.performed += Move; _input.GamePlay.Aim.performed += Aim; _input.GamePlay.Fire.started += StartFire; _input.GamePlay.Fire.performed += StopFire; _input.GamePlay.AltFire.started += StartAltFire; _input.GamePlay.AltFire.performed += StopAltFire; Now... How do I use multiple controllers (ie. multiple players) using this system? Is there an example using the current system? Ideally it'd be something along the lines of: Code (CSharp): _input.GamePlay.GetDevice(playerIndex).Move.performed += Move; I see that we can get a device id through the InputAction.CallbackContext, but that seems awfully clunky, and the id seems to be based on the connection number, so disconnecting and reconnecting the same controller won't give the same id. Thanks.
Code (CSharp): _input.GamePlay.GetDevice(playerIndex).Move.performed += Move; The equivalent of this is Code (CSharp): var player1 = _input.GamePlay; var player2 = player1.Clone(); player1.ApplyBindingOverridesOnMatchingControls(deviceForPlayer1); player2.ApplyBindingOverridesOnMatchingControls(ceviceForPlayer2); player1.Move.performed += Move; player2.Move.performed += Move; API is still clunky. Also, ATM you have to manage allocating devices to player yourself. I expect there ultimately will be APIs to help you with that. Overall, there's still various bits to improve around local multiplayer. But anyway, the central idea is that you have an action map with general bindings (say, for gamepad) and clone it so that each player gets a copy and then you "specialize" each copy on the specific device allocated to the player.
Cool, that'll do, thanks! Just a quick aside. I found an issue, when I call: Code (csharp): _input.GamePlay.Disable(); ...and the system gets input events I get spammed with errors. I have to call Disable() on every InputAction in _input.GamePlay, I'm pretty sure that negates the point of being able to call GamePlay.Disable(). Is this a known issue or should I get the error messages and post an issue to github?
Ok, that's not right indeed Not a known issue and I gave it a quick go and couldn't reproduce. Opening a ticket on GitHub with the errors would be great.
can u help me with the error @Rene-Damm ? Code (CSharp): public SkyHunters_Inputs inputsMap; public List<InputDevice> devicesInput = new List<InputDevice>(); public List<SkyHunters_Inputs> inputsMaps = new List<SkyHunters_Inputs>(); // Start is called before the first frame update void Awake() { inputsMap.SpaceShip.Join.performed += ctx => { var currentDevice = ctx.control.device; if (devicesInput.Contains(currentDevice)) return; var playerClone = new SkyHunters_Inputs(); playerClone.SetAsset(ScriptableObject.Instantiate(inputsMap.asset)); var Intvalue = InputActionRebindingExtensions.ApplyBindingOverridesOnMatchingControls(playerClone.SpaceShip, ctx.control); Debug.Log($"Some index return on Override Binding {value}"); inputsMaps.Add(playerClone); playerClone.SpaceShip.Shoot.performed += xControl => { PlayerShooting(); }; PlayerJoining(currentDevice); }; } the Intvalue return 0 every time!
@GilbertoBitt Could you show me the binding for Spaceship.Join and a Debug.Log of the ctx.control.path? Not yet sure whether it's the setup or whether it's a bug at work here that prevents the override from succeeding. BTW there's an easier way to do this now by just setting the `devices` property on the InputActionAsset. This way you don't have to go into overrides. Instead, you can just tell the actions to only bind to a specific set of devices. There's also InputUser which can handle most of the user/action management for you. We have some high-level MonoBehaviours in the pipeline that should make using this functionality a breeze (well, hopefully ). This includes player join support with no custom scripting required.
i still don't know howto pair device to input action asset! and inputUser i want to learn how to user on plataform that suport account pairing like xbox and on pc or others that don't have this funcion and how to attach more than one device like mouse/keyboard and other just one like gamepad. here is the project uploaded is a small project for testing this things. https://drive.google.com/file/d/16kH0Ks0IWwMSIaQQrMKrx5FTEX2kpDMf/view?usp=sharing
@Rene-Damm i change my MB_InputSystem to this! Spoiler: MB_InputSystem Code (CSharp): using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEditor.Graphing; using UnityEngine; using UnityEngine.Experimental.Input; using UnityEngine.Experimental.Input.Interactions; using UnityEngine.Experimental.Input.Plugins.Users; using UnityEngine.Experimental.Input.Utilities; public class MB_InputSystem : MonoBehaviour { public SkyHunters_Inputs inputsMap; // Start is called before the first frame update private InputDevice _keyboardInput; private InputDevice _mouseInput; void Awake() { _keyboardInput = Keyboard.current.device; _mouseInput = Mouse.current.device; inputsMap.SpaceShip.Join.performed += ctx => { var currentDevice = ctx.control.device; foreach (var device in InputUser.GetUnpairedInputDevices()) { Debug.Log(device); } if (!InputUser.GetUnpairedInputDevices().Contains(currentDevice)) return; var input = new SkyHunters_Inputs(); input.SetAsset(ScriptableObject.Instantiate(inputsMap.asset)); var user = InputUser.PerformPairingWithDevice(currentDevice, options:InputUserPairingOptions.ForcePlatformUserAccountSelection); if (currentDevice == _mouseInput) { user = InputUser.PerformPairingWithDevice(_keyboardInput, user, options:InputUserPairingOptions.None); } else if (currentDevice == _keyboardInput) { user = InputUser.PerformPairingWithDevice(_mouseInput, user, options:InputUserPairingOptions.None); } user.AssociateActionsWithUser(input); input.SpaceShip.Shoot.performed += context => ShootStarted(); input.Enable(); }; foreach (var user in InputUser.all) { user.actions.Enable(); SkyHunters_Inputs input = (SkyHunters_Inputs) user.actions; input.SpaceShip.Shoot.performed += context => ShootStarted(); user.actions.Enable(); //First Enable All than Disable it. input.SpaceShip.Join.Disable(); } } public void ShootStarted() { Debug.Log("Shooting"); } /*(bool, InputDevice, int) HasPlayerDevice(InputDevice currentDevice) { return devicesInput.Contains(currentDevice) ? (true, currentDevice, devicesInput.IndexOf(currentDevice)) : (false, currentDevice, -1); } void PlayerShooting(InputDevice controlDevice) { var index = devicesInput.IndexOf(controlDevice); Debug.Log($"Player Shooting using {index}"); } void PlayerJoining(InputDevice currentDevice) { Debug.Log("Player Just Join the Party!"); devicesInput.Add(currentDevice); Debug.Log(currentDevice); }*/ private void OnEnable() { inputsMap.SpaceShip.Join.Enable(); foreach (var user in InputUser.all) { user.actions.Enable(); } } private void OnDisable() { inputsMap.SpaceShip.Join.Disable(); foreach (var user in InputUser.all) { user.actions?.Disable(); } } } the only problem with it is that when using Xbox One Gamepad i'm not able to shoot unless i disconnect from pc and then reconnect again! then without the need to join again it start recoganizing the shooting action the keyboard and Mouse input work like a charm but has u r able to see i need make then current to get a copy/reference of InputDevice from keyboard and Mouse to then compare it inside the context callback without making then current! how i can solve the problem with Xbox One GamePad? it's becouse i use ForcePlatformUserAccountSelection on option? i will try change the option to see if work on pc without the need to reconnect the xbox one gamepad! maybe this will happen to any device but for now i only have xbox one to test it.
I'm having a hard time understanding how to implement this into my code, could you give me an example?
My initial suggestions are somewhat outdated by now. While the suggested setup is still doable, there are better ways now. The simplest way to set this up these days is PlayerInput. It will automatically take care of cloning actions and restricting them to controllers for specific players. Simply have multiple PlayerInputs in your game (either instantiated by you or through PlayerInputManager; see documentation). For doing it manually, there is a "devices" property on both InputActionAsset and InputActionMap now. Setting that will automatically restrict the given actions to just those devices. It's what PlayerInput does internally but is accessible as a general API.
Hey, I have 2 prefabs with separate PlayerInputs set up. It automatically detects the controllers and assigns a unique one to each which is wonderful. However, when I try to assign the input actions to generic gamepad south button, they apply to both characters for some reason. I'm using separate scripts and my unity version is 2019.2.5f1. Am I forced to use two different inputs specific to the controller? (for example cross instead of south button) Here is the input debugger: Thanks in advance
How do you set up those actions? Judging from the input debugger, it appears that those two actions are not associated with either player. They will thus go and bind to everything in the system. For actions to automatically be restricted to the devices of a player, they must belong to the same InputActionAsset as that assigned to the player (PlayerInput may duplicate the asset instance so it really must be the same asset instance used by a particular player).
I'm having the problem you described, where every device controls every player. I have a Player Input on each player object and this in my code. void Awake () { inputAction = new PlayerInputActions(); inputAction.Player.Jump.performed += _ => PlayerJump(); } Any time I press jump on any device, all players jump. What am I missing here? From the documentation, it sounds like it should assign a different device to each Player Input automatically, but I'm clearly breaking that functionality somehow.
To use multiple PlayerInput independently easily, you should use the PlayerInputManager, it will take care of that for you
I added a PlayerInputManager, joining players manually because I already had my spawning system all setup with the old input manager, and input debugger looks like the devices are correctly assigned, but it's still behaving the same way. I see two things there that make me think something is wrong that may be related to my problem, but I'm not sure how: 1) 50 actions per user. It should only be 10, but they're all being duplicated four times 2) All actions for the second user disabled
You're mixing code-generated input actions with PlayerInput. ATM the two don't yet go together. The code you posted will end up creating a set of input actions independent of PlayerInput. The code-generated path ATM has no support for control schemes and device pairing. So it ends up grabbing every possible device for every player. Thus the all-players-jump issue. PlayerInput, when instantiated more than once, will duplicate actions. With 10 actions in the asset and 4 players in the game, you should see 40 actions. From your shot it appears that you probably still have the "new PlayerInputActions" code in there. Removing that should result in the right amount of actions getting created. Not sure about that one. Would need more information.
Ah ok, that makes sense. Removing "new PlayerInputActions" does get rid of all of those actions. So then if I'm not instantiating the component in my script, how would I go about mapping those controls in my script? Every example I've seen from someone using this system has had that in there. Or do I just need to map them through the component in the editor with Send Messages etc?
The Quick Start Guide may be of use. But yes, you can map them through Send Messages or individually through UnityEvents. There will be an updated tutorial released soon that demonstrates this. The fact the tutorial posted on the blog showed the C# generation workflow was due to an internal communication mishap.
Hello everyone, I do not understand and need help. I want to have 2 characters that move every 1 with a single controller and I don't know how to do it. could you give me a guide or something that explains it in a simple way (or a script, and then I can use it to learn) Thank you. Here is a script in which I would like it to work: Code (CSharp): using UnityEngine; public class Move : MonoBehaviour { PlayerControl controls; //direction horizontal float inputHorizontal; private void Awake() { controls = new PlayerControl(); //inputs controls.Gameplay.Address.performed += ctx => inputHorizontal = ctx.ReadValue<float>(); controls.Gameplay.Address.canceled += ctx => inputHorizontal = 0; } private void Update() { //Move if (inputHorizontal != 0) { transform.Translate(new Vector3(inputHorizontal * 10f, 0, 0)*Time.deltaTime); } } private void OnEnable() { controls.Enable(); } private void OnDisable() { controls.Disable(); } }
Recommend switching to PlayerInput. Setting up multiplayer using the C# code generated from .inputactions files currently requires several pieces of custom scripting that can be avoided by using PlayerInput's built-in support for this kind of setup.
I have been working with the new input system 1.0.0. I have a player prefab created which has a Player Input component on it. The Player Input has an Input Actions attached to it. The Input Actions has a map created called "Player" and it has your basic actions on it. I then created a Player Input Manager and attached my player prefab to it. I then preceded to plug in two controllers and used the "Join Behavior: Join Players When Button Is Pressed". When one player joins they can navigate and it takes inputs from the controller. When another controller joins there is no input going to their player. The left stick of the first player is also manipulating the second players character. I was wondering if I am doing something wrong here? Is there any videos that explain this deeper? Thanks
But how to do it yourself? In that video - which is the only one I've found explaining something related to multiplayer - the PlayerInputManager spawns prefabs by itself. Your game may require something more complex, not just spawning a prefab. I guess we should use the Join Behavior 'Join Players Manually' option, but is there an example with that? (I manage to spawn players like in the video, at least) When I set that option, no script answers to the OnPlayerJoined message (not even the one that was answering when using the Join Players When Button Is Pressed)
Hi, I have found that ApplyBindingOverridesOnMatchingControls doesn't do what I have expected from it. Code (CSharp): public InputGroup(InputBinder inputBinder, Gamepad gamepad, CharacterController characterController, HammerController hammerController) { Debug.Log($"Device Id: {gamepad.deviceId}"); this._inputBinder = inputBinder; this._characterController = characterController; this._hammerController = hammerController; this._inputActionMove = this._inputBinder._inputActionMove.action.Clone(); // this._inputActionMove = new InputAction( // this._inputActionMove.name, // this._inputActionMove.type, // this._inputActionMove.bindings.ToArray()[0].path, // this._inputActionMove.processors, // this._inputActionMove.expectedControlType // ); this._inputActionRightStick = this._inputBinder._inputActionRightStick.action.Clone(); this._inputActionR2 = this._inputBinder._inputActionR2.action.Clone(); // if (lelSmellCode == 0) // { Debug.Log(this._characterController.transform.parent.gameObject.name); this._inputActionMove.ApplyBindingOverridesOnMatchingControls(gamepad); this._inputActionRightStick.ApplyBindingOverridesOnMatchingControls(gamepad); this._inputActionR2.ApplyBindingOverridesOnMatchingControls(gamepad); // lelSmellCode++; // } for (int a = 0; a < this._inputActionMove.controls.Count; a++) { Debug.Log($"InputActionMove Id: {this._inputActionMove.id} Control index: {a} Control: {this._inputActionMove.controls[a]} Control Device Id: {this._inputActionMove.controls[a].device.deviceId}"); } Debug.Log($"InputActionRightStick Id: {this._inputActionRightStick.id}"); Debug.Log($"InputActionR2 Id: {this._inputActionR2.id}"); } As you can see on the screenshot, even though I am passing the method a device with Id: 2, it still assigns a controlling device with Id: 1. Thus I have one device controlling both characters. I will have a look at how PlayerInput is implemented, but this one seems like a bug. And I cannot get local multiplayer to work this way. Thanks, Max
@Rene-Damm sorry to bother you, but is my question above a bug and should I file a bug or is it expected behaviour?
@Griz hi, I have seen your answer in a different thread and I presume that you have a knowledge of how new input system works in more detail than me. This question above about Code (csharp): .ApplyBindingOverridesOnMatchingControls(gamepad); - it's intended in this case to use the same action map but for multiple devices. I couldn't get this to work. I am using `InputActionReference` for this. I don't want to use `PlayerInput` because it's limited, enforces design, and has some overhead. Is there a way having `InputActionReference`s referenced in inspector, them using them as a base for input for some device. I am looping through `InputSystem.devices` and trying to assign a clones of action a different device but with no success.
I am also having issues with Player Input component. I filed an issue / bug in the github repo here 2 xbox one controllers are recognized in windows 10 as xinput and both are assigned to the same player, I can see that in the debug. I find it puzzling that the Tanks Demo does not have this issue. The gamepads are assigned correctly one to each user. I understand that the Player Input Manager is not always required, due that the Tanks Demo does not have it and the players get the proper gamepad assigned. Any ideas on what may be missing? wrong?
Is there a way to get all the input events and device information for multiple players? Using PlayerInput with Unity's messages only provides very limited information which I now need to work around a whole lot (including additional actions, duplicated code and manual state handling (touch start/cancel) because I can't acceess the device from the messages).