- Home /
Natural Jump algorithm
Hi,
I'm struggling to get my jump non linear. Right now, the character just rises and then falls, in very linear fashion. Using "Move", from character controller on other part of the code. The relevant part of the code is this:
function nJump() {
if (nJumping) {
nNewPos.y += jumpSpeed * Time.deltaTime;
if (!(nControl.collisionFlags & CollisionFlags.Above) && transform.position.y < nOldPos.y + maxJumpHeight) {
nCanFall = false;
}
else if (nControl.collisionFlags & CollisionFlags.Above || transform.position.y > nOldPos.y + maxJumpHeight) {
nJumpEnd = true;
nJumping = false;
nCanFall = true;
}
}
if (nControl.isGrounded && nJumpEnd) {
nGroundAfterJump = true;
nJumpEnd = false;
}
}
function nFall () {
if (!nControl.isGrounded && !nJumping && nCanFall && !nCanClimb) {
nNewPos.y = -gravity * Time.deltaTime;
nFalling = true;
}
else if (nControl.isGrounded && !nCanClimb) {
nFalling = false;
nCanFall = true;
}
}
What's making everything linear is probably this:
nNewPos.y += jumpSpeed * Time.deltaTime;
and this:
nNewPos.y = -gravity * Time.deltaTime;
No matter what I try, I just get some weird accelerations and non desired behaviors. Can you help me there?
You could use a projectile motion function. You could try to develop a script starting from y = 1/2at^2 + v(0)t+ y(0). Look over the internet for detailed explanation.
Hope that helps
I was thinking something like an exponential decrease/increase in your movement ins$$anonymous$$d of a linear decrease/increase.
Answer by Bunny83 · Feb 04, 2012 at 11:14 AM
Ok the way you handle your movement you can't really simulate accelerated movement. For this you need a speed variable that is changing over time.
So the usual procedure is to set or increase a speed variable to make the character move. To jump you just add a one-time vertical speed-boost. Gravity will bring your character down again.
private var velocity : Vector3;
var speed = 10.0;
var jumpSpeed = 12.0;
var gravity = Vector3(0,-9.81 ,0);
function Update()
{
if (nControl.isGrounded)
{
velocity = Vector3(Input.GetAxis("Horizontal") * speed,0,0);
if (Input.GetButtonDown("Jump"))
{
velocity.y += jumpSpeed;
}
}
}
function FixedUpdate()
{
if (!nControl.isGrounded)
{
velocity += gravity * Time.deltaTime
}
nControl.Move(velocity * Time.deltaTime);
}
Accelerated movement should be done in FixedUpdate which runs at a constant framerate.
Basically it's like the basic example from the CharacterController reference page
Guys, you rock! Really. I've made progress and got my character to respect game speed, even with acceleration and also had it slightly more natural. Fixed update did the trick.
Got into 2 new problems now:
Fixed update is delivering a jagged / stuttered movement, it's not just "slow motion", it looks like slow frame rate.
I've managed to get Character Controller $$anonymous$$ove command out of fixed update and kept only the gravity addition there - the character falls smoothly (without the stuttering animation), but I can't do the same with the Jump variable (as it's a one time setup). So the Jump doesn't slow down at slow motion, at all.
I'm running in circles here lol
You can sometimes get a stutter if the camera movement code is in a different Fixed/non update as the player.
The "proper" way to perform move code is everything that changes over time (Controller.$$anonymous$$ove) in FixedUpdate, to make it frame-rate independant. $$anonymous$$eyboard reads have to be in Update, but they can just set vars that are used later.
Indeed everything (aside from move and position variables) are at FixedUpdate. Everything else, including input, are at Update. The camera is stationary right now, the "low frame rate" effect on movement (when in slow motion) seems to be something exclusively related to having the $$anonymous$$ove function inside FixedUpdate. Perhaps there is some kind of animation "Sample rate" that I must change when in slow motion?
I got the slow motion running correctly now (with $$anonymous$$ove) control. This is what I found out:
As you guys masterfully explained, every exponential calculation must be placed at Fixed Update.
Character controller "$$anonymous$$ove" must be at "Update", otherwise it does "low sample rate" the animation
Now here comes the trick: "$$anonymous$$ove" must be toned down, otherwise, it actually speeds up when in slow motion. This is my final move command: nControl.$$anonymous$$ove(nNewPos * Time.timeScale);
I guess that's it. It's working nicely now, but let me know if I'm doing something weird that will cause me trouble along the road.
Answer by junaum · Feb 04, 2012 at 04:44 AM
Thank you. I've researched some projectile motion stuff, and the "character move" sample from Unity Reference. Made some progress, but couldn't get my functions to work properly yet.
Right now, I got this for gravity: nNewPos.y -= gravity Time.deltaTime Time.timeScale;
And this for jump: nNewPos.y += jumpSpeed Time.deltaTime Time.timeScale;
They kind of work smoothly, but the jump accelerates a in the middle of the motion (instead of the begining)... and both animations don't respect Time.timescale (therefore, it can't be slowed down, or keep the same speed on different computers). I've tryied with the * Time.timescale, and without it.
Would you point me a direction to fix this, and still keep the smooth jump/grav effect?