Physics behaving differently when switching controls from Input.GetKeyDown to Input.GetAxis - C#

I’m pretty new to this programming lark, but every problem I’ve come across so far I’ve managed to find a solution to. This one however has finally driven me to ask a question. Google doesn’t know, and Its broken me.


My requirements:
I want the user to be able to assign whatever button they want to make the character jump by using the Input Manager.


The issue:
my previous code using Input.GetKeyDown works perfectly, but I have now amended this to use the Input Manager (via Input.GetAxis) and it appears that 1 of 3 things (or a combination of these) is happening:


  1. The player mass is lighter
  2. The jump force is greater
  3. Gravity is weaker
    .

As a result the character accelerates off of the screen at an insane speed, and takes a good few seconds to come back down to solid ground.


Interestingly, if I decrease the public jump force variable for the player in the inspector (from 90 to about 20) I get a similar-ish jump to before, but it is erratic: the jump height alters with each and every jump (almost as if a slightly different amount of force is being applied each time).


Previous code:

public float jumpForce = 90f;
Rigidbody2D rb2d;

void Start ()
{
	rb2d = GetComponent<Rigidbody2D>();
}

void FixedUpdate ()
{	
	if (Input.GetKeyDown (KeyCode.Keypad0))
	{
		jump ();
	}
}

void jump ()
{
	rb2d.AddForce (new Vector2 (0, jumpForce));
}

New Code:

public float jumpForce = 90f;
Rigidbody2D rb2d;

void Start ()
{
	rb2d = GetComponent<Rigidbody2D>();
}

void FixedUpdate ()
{	
		jumpDetector = (Input.GetAxis ("Jump"));

		if (jumpDetector > 0)
		{
				jump ();
		}
}

void jump ()
{
	rb2d.AddForce (new Vector2 (0, jumpForce));
}

Input Manager settings
(ignoring any settings that are blank or unticked)
Name: Jump
Positive Button: space
Gravity: 1000
Dead: 0.001
Sensitivity: 1000
Type: Key or Mouse Button
Axis: X axis
Joy Num: Get Motion from all Joysticks


Player Rigidbody2D Settings:

Body Type: Dynamic
Material: None
Simulated: Ticked
Use Auto Mass: No
Mass: 0.35
Linear Drag: 0
Angular Drag: 0.05
Gravity Scale: 1.3
Collision Detection: Discrete
Sleeping Mode: Start Awake
Interpolate: Interpolate
Freeze Position: No
Freeze Rotation: Yes


Physics2D Settings:
X: 0
Y: -10
Default Material: None
Velocity Iterations: 8
Position Iterations: 3
Velocity Threshold: 1
Max Linear Correction: 0.2
Max Angular Correction: 8
Max Translation Speed: 100
Max Rotation Speed: 360
Baumgarte Scale: 0.2
Baumgarte Time Of Impact: 0.75
Time To Sleep: 0.5
Linear Sleep Tolerance: 0.01
Angular Sleep Tolerance: 2
Default Contact Offset: 0.01
Queries Hit Triggers: Yes
Queries Start In Colliders: Yes
Change Stops Callbacks: No


I would kill for any sort of advice on this. I was about 5 inches away from a finished game, and it feels like the finish line has just been moved another 30 miles.

Thanks in advance!

I DID IT!!!


I can only come to one logical conclusion for the behaviour change.


Input.GetKeyDown only returns true for the frame in which it was pressed, which means it almost immediately becomes false and therefore can only apply the jumpForce once.


The code I had written for Input.GetAxis behaves in exactly the same way as Input.GetKey, where it returns true for as long as the button is pressed. If I held the jump button for 4 frames the jumpDetector variable would be greater than 0 for all 4 frames, and therefore the jumpForce would be 90*4. This also explains why the jump height was inconsistent.


So how did I fix it?


While researching all of the different input options I came across Input.GetButtonDown. I had previously ignored this because I assumed this was essentially Input.GetKeyDown for Joypads, but having exhausted every other avenue possible, something in the description finally jumped out at me:


“Returns true during the frame the user pressed down the virtual button identified by buttonName.”


IT USES THE INPUT MANAGER!!!


New code below:

	public float jumpForce = 90f;
	Rigidbody2D rb2d;


	void Start ()
	{
		rb2d = GetComponent<Rigidbody2D>();
	}

	void Update ()
	{    
		if (Input.GetButtonDown("Jump"))
		{
			jump ();
		}
	}

	void jump ()
	{
		rb2d.AddForce (new Vector2 (0, jumpForce));
	}

I also moved the jump function into Update, it just seemed to respond better than FixedUpdate.


Needless to say it works perfectly and I feel like an idiot. I can only hope this stops someone else from tearing their hair out!