I am very happy to work with the New Input System and all the controls related issues I have with the old system was quite easy to fix here. Now I am ready for the next step in the development of my local coop game. The character selection screen!
So it should join a player, when a specific button is pressed on a keyboard or a joystick.
Here is an example from Spelunky (not my images): Imgur: The magic of the Internet
Do anyone have a nice example of this to work from? Any help is much appreciated =)
There’s not much guidance/docs ATM for how to do this without PlayerInput. In general, I’d recommend looking at some of PlayerInput’s code and following its example. The basics, however, are pretty simple.
InputUser simplifies dealing with multiple users that should have separate inputs. Each user can have one or more paired devices, a set of actions, and an active control scheme. All of these are optional.
To set up a basic join-on-button-press, you can listen for unpaired device activity and pair devices to users from within the callback.
++InputUser.listenForUnpairedDeviceActivity;
InputUser.onUnpairedDeviceUsed +=
(control, eventPtr) =>
{
// Ignore any use of a control that isn't a button.
// NOTE: InputUser has already filtered out a bunch of stuff
// at this point so we know we're looking at meaningful user
// interaction already.
if (!(control is ButtonControl))
return;
// Join a player.
// NOTE: PlayerInput does this in a much more flexible manner but
// for simplicity, let's just hardcode things here.
var device = control.device;
var controlScheme = default(String);
if (device is Keyboard || device is Mouse)
controlScheme = "Keyboard&Mouse";
else if (device is Gamepad)
controlScheme = "Gamepad";
else
return; // No control scheme.
var user = InputUser.PerformPairingWithDevice(device);
var user.AssociateActionsWithUser(new MyGeneratedCSharpActionsWrapper());
user.ActivateControlScheme(controlScheme)
.AndPairRemainingDevices(); // For keyboard&mouse, grab device pair.
var player = GameObject.Instantiate(myPlayerPrefab);
player.GetComponent<MyPlayerInput>().user = user;
};
I can share some of it. However I have some scene loading mechanism in as well. So I will chop that out for simplicity.
I am ONLY allowing joysticks ATM.
Is Input.Menu and has a movement, ready and back action.
using System;
public class PlayerSelectionManager : MonoBehaviour
{
public List<PlayerSelectionCanvas> PlayerSelectionCanvases;
void Start()
{
InputUser.listenForUnpairedDeviceActivity++;
InputUser.onUnpairedDeviceUsed += InputUser_onUnpairedDeviceUsed;
}
private void InputUser_onUnpairedDeviceUsed(UnityEngine.InputSystem.InputControl control, UnityEngine.InputSystem.LowLevel.InputEventPtr inputEvent)
{
if (control.ToString().Contains("Mouse") || control.ToString().Contains("Keyboard"))
return;
if (control is ButtonControl)
{
print($"Registering device({control.device.deviceId})!");
var device = control.device;
var user = InputUser.PerformPairingWithDevice(device);
user.AssociateActionsWithUser(new MasterInput());
user.ActivateControlScheme("");
//Creates a new user on this object, it is used to save selections and is passed on to a PlayerManager in the scene that is loaded later (removed from the code)
var selectionUser = gameObject.AddComponent<PlayerModelSelector>();
selectionUser.input = user.actions as MasterInput;
selectionUser.SelectionCanvas = PlayerSelectionCanvases.First(x => !x.IsUsed);
selectionUser.SelectionCanvas.PlayerJoined();
selectionUser.UpdateControls(); //Setup controls from the selectionUser input and the SelectionCanvas.
}
}
private void OnDestroy()
{
InputUser.onUnpairedDeviceUsed -= InputUser_onUnpairedDeviceUsed;
}
}
The PlayerModelSelector has verify simple things right now. They are all based on input and update the SelectionCanvas which is dependent on your game and the game state (prototype, alpha etc. ). I change the color of the playerModel to differentiate between the players (Later maybe the models as well).
3 and 4.
You can do in the start method
DontDestroyOnLoad(gameObject);
Then you can load a new scene with SceneManager.LoadSceneAsync(1, LoadSceneMode.Single);
On the event SceneManager.sceneLoaded. you can subcribe with a function that locates the PlayerManager and spawn the players the correct places.
The hardest part, for me, was getting the hang on 2. The rest came in acceptable speed.