Given the following code using the new Input System I am trying to make a local multiplayer game. When connecting controllers and pressing a button, another player will join; this is as intended. However, the 2nd controller will work for both players; additional controllers do the same. Regardless of the default scheme, both inputs seem to work on both players at the same time. Formerly I had separate but nearly identical Player 1 and Player 2 action maps, with only Player 2 lacking keyboard input. While this was seemingly successful in that keyboard input remained tied to only player 1, the controller input would still apply to both. What am I doing wrong here?
Formerly I had individual mappings for Xbox, PS4, PS5, and switch but I removed those. Not sure if that matters here but I am fairly lost so I will mention everything I have changed recently while trying to add multiplayer. I also added this. to a number of things to try and make it as object specific as I could but seemingly didn’t change anything.
public void Vertical(InputAction.CallbackContext context)
{
v = context.ReadValue<float>();
}
public void Horizontal(InputAction.CallbackContext context)
{
h = context.ReadValue<float>();
}
public void Punch(InputAction.CallbackContext context)
{
if (context.performed)
{
if (!this.downed))
{
if (!this.attacking)
{
//replaced with pseudocode for sake of post
if (!anim playing == ("Attack1") || "Attack2") || ("Attack3"))
this.unitController.PlayAnim("Attack1");
}
if (this.InputBufferCounter > 0) //Checking if Buffer is available
StartCoroutine(PunchLogic()); //Calling Punch Logic
}
}
}
public void Jump(InputAction.CallbackContext context)
{
if (context.performed)
{
if (!downed))
{
if (InputBufferCounter > 0)
{
if (!this.anim.GetCurrentAnimatorStateInfo(0).IsName("Air Attack"))
{
if (!jumping && !this.downed) || !this.interacting && !this.downed))
{
this.unitController.PlayAnim("Jump");
StartCoroutine(JumpLogic());
}
}
}
}
}
}
public void Item(InputAction.CallbackContext context)
{
if (context.performed)
{
if (!this.downed)
{
//Items not finished this is just to test downed state for now
this.unitController.PlayAnim("Fall");
}
}
}
Once you’ve set that up, set up a tiny script to read and print the values for each player.
Until you absolutely positively control one set of numbers with the player1 inputs and one stack of numbers with the player2 inputs, don’t do anything else.
Fix all your errors. Google for how. Errors have solutions.
Until you fix all your errors, you’re possibly just chasing a ghost: once ANY error happens, 100% of anything else the software does is in question.
Remember: NOBODY here memorizes error codes. That’s not a thing. The error code is absolutely the least useful part of the error. It serves no purpose at all. Forget the error code. Put it out of your mind.
The complete error message contains everything you need to know to fix the error yourself.
The important parts of the error message are:
the description of the error itself (google this; you are NEVER the first one!)
the file it occurred in (critical!)
the line number and character position (the two numbers in parentheses)
also possibly useful is the stack trace (all the lines of text in the lower console window)
Always start with the FIRST error in the console window, as sometimes that error causes or compounds some or all of the subsequent errors. Often the error will be immediately prior to the indicated line, so make sure to check there as well.
Look in the documentation. Every API you attempt to use is probably documented somewhere. Are you using it correctly? Are you spelling it correctly? Are you structuring the syntax correctly? Look for examples!
All of that information is in the actual error message and you must pay attention to it. Learn how to identify it instantly so you don’t have to stop your progress and fiddle around with the forum.
So I reverted it to the player 1 and player 2 near identical mapping and used the input debugger to see this. This is exceptionally strange as it says it is all disabled despite the actions working. My OnEnable checks if it is player 1 or 2 and then enables the corresponding inputs.
Yeah fair enough, I should’ve just looked it up as I previously assumed that it was a possibly common issue I’m sure someone else asked about it. The Error is that it fails to call a related function to a button since that prefab wasn’t created yet. After the player spawns or if I press a button that is not related to an existing action there are no more errors and it works (save for controlling both players) as intended.
Keep at it until you have two streams of numbers controlled by separate input action sets in a tiny script.
If you can’t separate two streams of numbers, check your work over with the steps listed in the docs… it’s easy to miss a step.
Only once you have that can you even consider anything else like enabling / disabling, hooking up any other game stuff, etc.
Set yourself up for success by chopping your problems into the tiniest possible steps until you find where the issue (or issues) is (or are). Remember: bugs are like cockroaches. It’s rare there is only one.
So I went back and tried to rewrite stuff. They’re separated so that’s good, however now mouse actions don’t register (adding keyboard replacements worked but is not ideal), and the punches are acting differently than before.
Still while you didn’t directly answer it for me thanks for being so frank and suggesting going back to the start with it. I had been under the impression you needed to have OnEnable and OnDisable for input actions. Removing that seemed to be what allowed the players to act as their own. That even extended to being able to have a universal Player input map and not a Player 1 and Player 2 map.
I need to re-read a lot of input system things and watch more videos I feel like a lot of things I had done are not working together as I thought they did. Thanks for the help, might need to post again if I can’t figure out how to get the actions to act as they used to.
Unity projects support references at a lot of different levels and this can cause a lot of confusion.
For instance you can make a public GameObject MyThingy; and drag either a Prefab (asset on disk) into it, or something already in the scene, which might be a prefab… or prefab variant… or might just be something in the scene!
Obviously for a prefab you would have to Instantiate() the prefab and then retain a reference to what you instantiated before it would exist in the scene.
Obviously for something already in the scene (prefabbed or not), you would not do that, or you would get two copies.
This is just one example but it applies to pretty much anything you can slot into another thing, such as Materials, Textures, Input Actions, etc.
This makes it important to keep in mind “where what is what” as you’re working. It does take time to get used to and we all still make mistakes occasionally, but the idea is to have the mental toolset to go finding out what you actually did versus what you intended to do.