Hello, i am relatively new to Unity’s new Input System as it is my 3rd time using this system. I have been trying to rack my head around getting a specific type of input down for a game that i am working on but i cant get it to work.
The input i desire is similar to Input.GetKeyDown, where the input only sets itself true upon pressing a button once. I have searched around the internet for some reference with no luck.
I have tried using the context.started boolean but that does nothing.
I have also tried using the Interactions menu in the InputMenu which also does nothing.
Does anyone have any good implementations or ideas as to how to get about creating this behaivour?
Oh, didn’t know it was an option. Maybe i will use this in the future.
However, I am using a Input Actions asset for most of my inputs since it helps my colleagues with setting inputs without any hassle.
I have read through that documentation actually. I have tried most of the methods and variables that lie with the examples and explanations. The primary ones that i have tried is assigning a method specifically to a desired state (such as having input that happen at the start of the frame being called at Action.started), as well as manually checking the state of the current input using the CallbackContext.phase to see in which exact phase the current input is in. Neither of these methods work at all (Action.started gets called constantly and the CallbackContext.phase sometimes never reaches certain states such as Started or Cancelled).
I may have implemented both methods wrong though (and i sure hope that it is indeed the case) but as of this moment, i cant think of anything that can work.
Below is the current implementation of what i have written. It is a seperate class that handles and extends from the PlayerControls InputActions class. For the sake of testing our game, i decided to include Unity’s old input and swap between the two inputs using a boolean.
The GameHandler.CoreManager contains eventListeners that allows this class to use Unity’s Update, OnEnable and OnDisable methods. They have worked so far with no problems.
You said you need an input where the action happens once on a keypress. Like jumping when you hit the spacebar or something. You need the performed action for that.
Also read up and make sure you set up the Interactions properly in case you need something different (press the “E” button for 2 seconds for interact-style controls)
I have tried a performed action for that and it still kept being called every frame instead of just being called upon using the input. Taking Interact by example: controls.Player.Interact.started+= ctx => { Interact = ctx.ReadValue<float>() == 1 && !pauseInput; }; controls.Player.Interact.performed+= ctx => { Interact = ctx.ReadValue<float>() == 1 && !pauseInput;
both of these lines behaive the same.
Furthermore, if i use the CallbackContext states like this: controls.Player.Interact.performed+= ctx => { Interact = ctx.started && !pauseInput; };
the same behaivour still presists, where the input keeps getting called at all times instead of just once at the start.
I have read about the Interactions property and i still find it very confusing in terms of setting up the settings to get a desired result. Maybe you or other people know a specific setting(s) that allow one to make an input trigger once instead of every frame.
I’m not sure about your setup, I found your class a bit confusing at first sight, but maybe because it’s just strange for me doing things like this.
But I guess, you only(!) need this for the interaction:
And then wherever you’re actually perform the interaction you can set the Interact bool to false. You have made an assumption which is not true, naming that you assumed that the performed action is called every frame, but this is not the case. The performed is called ONCE per action (hit the spacebar, one performed call in the very next frame). Your problem is that your Interact boolean stays true after that. I think.
Just tested a very crude implementation of your suggestion, i can say with confidence that it works.
Here is how i did it:
I set my Interact input to set my Interact to true (or !pauseInput, thanks for that catch) like so: controls.Player.Interact.performed += ctx => { Interact = !pauseInput; };¨
Then in the Update Method, rigth after the check to use the oldInput, i set the Interact input to false, like so:
public void InputSystemActionESC(InputAction.CallbackContext btn)
{
if (btn.started) //detect started action, like old keydown.
{
ActionESC = !ActionESC; //trigger my bool when keydown
}
}