- Home /
Modify Rigidbody2D Jump distance
I'm using rigidbody2D.velocity to move my character around based on keyboard input. Is there a way to modify the distance portion of the velocity when the character jumps? Right now, the character jumps way too far. I'm currently using addforce, but that doesn't seem to get me what I want. I pretty much want to half the distance while keeping the time the same.
EDIT: Here's my current code for the character controller:
using UnityEngine;
using System.Collections;
public class AvaController : MonoBehaviour
{
public float maxSpeed = 5f;
private bool facingRight = true;
Animator anim;
bool grounded = false;
public Transform groundCheck;
float groundRadius = 0.2f;
public LayerMask whatIsGround;
private float move;
public bool jumping = false;
public Vector2 jumpForce = new Vector2(120f, 330f);
void Start()
{
anim = GetComponent<Animator>();
}
void Update()
{
print (rigidbody2D.velocity.x);
print (jumping);
// Allow jump in FixedUpdate
JumpUpdate();
// Play crouching animation
if( grounded && Input.GetKey(KeyCode.S) )
{
anim.SetBool("Crouching", true);
}
else
{
anim.SetBool("Crouching", false);
}
}
void FixedUpdate()
{
// Check to see if the player is touching a "ground"
grounded = Physics2D.OverlapCircle(groundCheck.position, groundRadius, whatIsGround);
anim.SetBool("Ground", grounded);
Jump();
// If player is not on the ground, player cannot control the character
if (!grounded)
return;
if (anim.GetBool("Crouching") == false)
{
move = Input.GetAxis("Horizontal");
anim.SetFloat("speed", Mathf.Abs(move));
rigidbody2D.velocity = new Vector2(move * maxSpeed, rigidbody2D.velocity.y);
}
if( (move > 0) && (!facingRight) )
Flip();
else if( (move < 0) && (facingRight) )
Flip();
}
void JumpUpdate()
{
if (!jumping) {
if( (anim.GetBool("Crouching") == false) && grounded && Input.GetKeyDown(KeyCode.Space) )
{
jumping = true;
}
}
}
void Jump()
{
if(jumping)
{
rigidbody2D.AddForce(new Vector2(0f, jumpForce.y));
anim.SetFloat("vSpeed", rigidbody2D.velocity.y);
anim.SetBool("Ground", false);
if(rigidbody2D.velocity.x != 0)
{
rigidbody2D.AddForce(new Vector2(-5.8f, 0f));
print (rigidbody2D.velocity.x);
}
else
{
rigidbody2D.velocity = new Vector2(0,rigidbody2D.velocity.y);
}
if(rigidbody2D.velocity.y == 0)
jumping = false;
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 avaScale = transform.localScale;
avaScale.x *= -1;
transform.localScale = avaScale;
}
}
This works perfectly if I comment out the rigidbody2d velocity in my horizontal movement code, but then they character can't move left or right.
In your Horizontal movement code, are you by chance setting the Y velocity to 0? It should be Vector2(horizontal$$anonymous$$ovement,rigidbody2D.velocity.y);
Also, that last line in this code is not doing anything, you're setting rigidbody2D.velocity to itself, that isn't adding anything to the equation.
$$anonymous$$y horizontal movement code is
rigidbody2D.velocity = new Vector2(move * maxSpeed, rigidbody2D.velocity.y);
It does work, just not how I'm trying to make it work. Right now, the character is moving 10 units when velocity.x is at 1. I only want the character to move 5 units but i don't want to affect the velocity while in the air. I just want a smaller jump.
Your explanation is confusing... If you don't want your horizontal control affecting the jump velocity, then set a condition for if(grounded). Also, you're only setting the grounded bool for your animator, and not this script here. Put the jump code before your movement code, and have it set grounded = false when activated, then your horizontal movement code won't operate until grounded again.
I'll try to explain it a bit more clearly. When the player is running and presses the jump button the character's velocity.y starts increasing until it reaches a certain jump height. It then descends until the player is back on the ground. Currently, there are 10 units in between the starting jump position and the end jump position.
I would like to decrease the jump length from 10 units to 5 units.
That should be as simple as halving the movement calculations you're making then... So I don't see the problem.
Answer by Dizmiester · Mar 02, 2014 at 03:29 AM
You're jumping on Update but moving on FixedUpdate? AddForce on FixedUpdate as its a physics calc You can check for the jump button on Update then action it on FixedUpdate.
Adding force is not an incremental thing in your script it just adds a force.
For mass of 1.
force = mass * acceleration
force = 1 x acceleration.
adding force will accelerate the rigid body over time. In the y vector that speed will be restrained by the negative acceleration applied to the rigid body by gravity.
Going up at 330units / sec / sec, but decelerating at 9units / sec / sec. eventually gravity wins and the speed is 0 and you have your max height before you start falling. The max height is set by the time relationship between your jump force and gravity. If you decreased the jump force.y you wouldn't get as high, but wont travel as far because you would be in the air for less time.
You want it to jump as high but not as far?
decreased the jumpForce.x
remember that the jumpForce.x is in addition to your current speed (velocity) so adding force will add acceleration to the velocity of the rigidbody horizontally.
note: (You can try negating the current speed by saying
rigidbody2D.velocity = new Vector2(0, rigidbody2D.velocity.y);
in the beginning of your jump function. Unless you want to jump further when traveling faster) I've not played too much with using AddForce to move a controllable rigidBody but the logic here makes sense.
It will accelerate slower forwards meaning that by the time the jumpForce.y has taken you up to your height and back down you've traveled forward less. Then when you're grounded the movement calc takes care of slowing you down by setting your velocity.x.
With a bit of trial and error with setting your jumpForce.x you can set a distance in x the rigidbody will move during its rise and fall. There are equations that will allow you to work out -> for any given amount of seconds, when going from a speed of 0, how many meters will you travel if constantly accelerating at N meters per sec per sec. But i don't know them off by heart.
A bit long winded but maybe that helps?
Thanks for this. It is helpful but still doesn't quite solve my issue. And yea, I want the player to jump as high as I have it right now but not as far.
$$anonymous$$y issue is with the AddForce method. Adding force to the vertical velocity works perfectly fine. The character accelerates upward and accelerates back to the ground based on gravity. Adding force to the horizontal velocity seems to make the character just move forward instantly. It's not a smooth movement like it is when adding force to the vertical velocity.
I can't figure out why adding force to the horizontal velocity would cause a different behavior.
The behavior is different because gravity is vertical... That's how physics works. Also, as I mentioned in my comment earlier, you'r currently Adding Force to your existing horizontal velocity. Ins$$anonymous$$d of using AddForce, just use rigidbody.velocity so that the force isn't added to the existing horizontal force.
Ok I understand, as Invertex says the difference is that the upwards force being applied is effected by another AddForce which is automatically applied by the physics engine. So your script adds an upward force and the physics engine adds a negitive force. To understand what is going on you need to have an understanding of how those forces are applied by the physics engine and your script.
The Physics engine is complicated but I'll try and simplify it for sake of explanation.
The physics engine is constantly adding a speed of -9.8m/s every second. If we break this down again it actually adding a speed of -9.8m/s * the time between FixedUpdates or 0.2seconds.
Remember Force = acceleration (if your rigidbody has a mass of 1 ).
accerleration = speed per sec.
So basically every FixedUpdate $$anonymous$$using 1.96m/s from your velocity.y, making it $$anonymous$$us 9.8m/s every second.
Your script only works on the next FixedUpdate after Jump() is called
So your script only adds a force for 0.2 seconds (the length of 1 FixedUpdate ) say 120m/s * 0.2seconds giving you a velocity.y of 24m/s at the start of your jump.
Physics Engine then adds gravity every FixedUpdate between then and when you land. gradually slowing your speed until it is 0 then goes into $$anonymous$$us speed which makes you fall.
If you want to have this ramp effect on your horizontal movement, you need to have another force being applied which is the inverse of your JumpForce.x like say "AirDrag"
Setting AirDrag to something similar to gravity would produce the same effect but it would need to be applied over a period of time rather than just one FixedUpdate Say You have a variable called jumping which gets set to true when the jump button is pressed but gets set to false when you land.
Then you could say
if(jumping){
rigidbody2D.AddForce(new Vector2(-1.96, 0));
}
This would slow your speed in the x-axis by 1.96 every FixedUpdate until it was 0 but would then move you backwards so you would need to restrain it by saying something like
if(jumping){
if(rigidbody2D.velocity.x > 0){
rigidbody2D.AddForce(new Vector2(-1.96, 0));
}else{
rigidbody2D.velocity = new Vector2(0,rigidbody2D.velocity.y);
}
}
This would then apply an drag force to your horizontal speed until that speed reached close to 0
I'm not sure if that's the effect you're after but that's how to simulate the physics of what I think your asking.
As Invertex is saying you could do all this by applying changes to the velocity.x and velocity.y ins$$anonymous$$d as that's all that AddForce is really doing anyway.
It just does it in relation to the objects mass variable. If the Rigidbody's mass is 1 then AddForce only called on one FixedUpdate and setting velocity is near enough the same as far as the physics engine is concerned.
Just remember that AddForce is speed over the period that the force is applied ( 0.2 seconds per FixedUpdate ) where as setting the velocity is a command to say
"this is the speed!"
and if you set that speed each FixedUpdate the speed is still the speed. Whereas if you AddForce every FixedUpdate its like saying add this
"speed to the current speed"
Ok as you can see I like Physics and explaining Physics so may have got a bit carried away. I'll go find some other physics based questions to answer now..
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Unity 2D Jump script wont work on android but does on PC? 0 Answers