Hey, Just started learning C# to port my 2D UE4 game to Unity, so far i'm learning quickly but while coding a jumping mechanic i'm encountering a weird issue that some of you might be able to explain. Here's the code Code (CSharp): //If on the ground and pressing jump, throw player in the air if (grounded && Input.GetButtonDown ("Jump")) { isJumping = true; body.AddForce (new Vector2 (0, jumpForce)); } //If jumping, going up and releasing jump button, stop his upward velocity if (Input.GetButtonUp ("Jump") && isJumping && body.velocity.y >= 0) { isJumping = false; body.velocity = (new Vector2 (0, 0)); } Everything works perfectly, however when i tap and release the jump button extremely quickly, the player jumps at full height ignoring the second if statement's velocity change. I have used Debug.Log after every if statements and both get executed in the proper order. So why isn't it setting the velocity to 0 when the button is being pressed and released very very quickly? It's as if the AddForce takes more time to kick in, therefore when pressed extremely quickly the velocity gets changed before, it makes no sense to me. Here's another example of what i don't understand By adding these lines to the Start function: Code (CSharp): void Start () { body.AddForce (new Vector2 (0, 500)); body.velocity = (new Vector2 (0,0)); } I don't understand why the character is being thrown in the air, since i'm setting it's velocity to be zero right after i have added some force Some help would be very appreciated!
by any chance is that code in FixedUpdate? generally if you want fast responsive input but want to use physics you need to check for input in Update (runs every frame) and pass/reference/cache/whatEverYouWantToCallIt the data so you can use it in the FixedUpdate (runs at a default 50fps, so not every frame) function to perform the physics movement. If you use Input in fixedupdate you can get into the situation where the input is missed (i.e. the down frame was detected but the up frame was missed)
I don't understand because the AddForce is being completely stopped by setting the velocity to 0 even if the press and release is happening very fast, but when done even faster (nearly at the same time with a flick of the finger on the button) , the set velocity doesn't have any effect, it's as if it's setting the velocity so fast that it happens before the AddForce had time to push the player up, so it ignores the set velocity and proceeds to push the player up Is there a simple way around that?
it's the same thing just the other way around. You are passing several updates to the rigidbody between the fixedupdate calls. The FixedUpdate is called immediately before each physics "tick", nothing happens with forces outside of those ticks. https://docs.unity3d.com/ScriptReference/Rigidbody.html
I'm not sure i understand as i do not use the FixedUpdate for my jump since i'm only adding force for a single frame at the push of a button and not over a period of time, as i said it happens in Update Can someone explain the second example that i posted with the Start function, that would help me understand my issue Code (CSharp): void Start () { body.AddForce (new Vector2 (0, 500)); body.velocity = (new Vector2 (0,0)); } I want to know why setting the velocity isn't stopping the AddForce, i'm sure it would if there was a slight delay between them
I don't know the answer for sure, but I assume that when you add a force in Update or Start, it's essentially queueing the force so that it will be applied when the physics step (FixedUpdate) happens. But setting the velocity happens instantly. So you're basically saying "When physics happens, add a force. Also, right now the velocity is zero."... the force is still queued up, so it's going to happen when the physics step kicks in. Similarly, in your other code, when you set the force, it's getting queued and if you release the button before the physics step happens, it sets the velocity to zero (which it probably already is) before the force has been applied, but then when physics kicks in, the force is still there and gets added. This is all especially true if your rigid body has "interpolate" turned off. The physics timestep happens every .02 seconds, so if you press the button fast enough, it could be down and then back up before the force ever gets applied. TLDR: Use either forces OR velocity, don't try to use them both at the same time. You should probably change your jump to something like this: Code (csharp): if (grounded && Input.GetButtonDown ("Jump")) { isJumping = true; body.velocity = (new Vector2 (0, jumpForce)); } //If jumping, going up and releasing jump button, stop his upward velocity if (Input.GetButtonUp ("Jump") && isJumping && body.velocity.y >= 0) { isJumping = false; body.velocity = (new Vector2 (0, 0)); } You'll need to have gravity turned on or do some kind of fake gravity, but I assume you have something like that already.
makeshiftwings, thank you so much, that definitely seems to be what is happening, it makes perfect sense, i was about to lose my mind here. I'll give what you suggest a try, i have no doubt it will work Thanks again