- Home /
When stopping Rigidbody.velocity 1 frame stutter C#
Hi,
I'm having a hard time getting a smooth character movement in my game. I'm creating a 8-way movement. Moving my player with rigidbody.velocity is causing a 1 frame stutter when the movement stops.
This is the script I'm using to move my player, and I'm running it in FixedUpdate().
movesides = Input.GetAxisRaw ("Horizontal");
moveupdown = Input.GetAxisRaw ("Vertical");
GroundCheck();
velocityY = GetComponent<Rigidbody>().velocity.y;
Vector3 currentVelocity = new Vector3 (movesides,0,moveupdown);
Vector3 currentVelocityNormal = currentVelocity.normalized;
normVelocityX = currentVelocityNormal.x;
normVelocityZ = currentVelocityNormal.z;
GetComponent<Rigidbody>().velocity = new Vector3 (normVelocityX * currentSpeed, velocityY, normVelocityZ * currentSpeed);
here is a gif of the issue: https://media.giphy.com/media/3oz8xLzOcsMJE2tSQo/giphy.gif
My enemy Ai runs with Rain Ai behaviour trees, and have a character controller component (my player has a rigidbody) to help with the step heights and what not . Having my players rigidbody to interpolate is the only way I have found to have player and enemy movement fluid. At first I thought it was a camera issue with interpolation issue. So I tried the following things:
If i change interpolate to none and the camera is parented to the player, the original stutter problem is gone, but while the player is moving, a small stutter appears on the objects that are not moving and all my enemies movements will look extremely choppy
If I un-parent the camera from any objects and set the interpolation to none, my player will move with a small constant stutter and my enemy movement looks fine.
If I un-parent the camera from any object and set the interpolation to interpolate, the small stutter at the end of movements is visible.
Using Scripts to move the camera in FixedUpdate or LateUpdate brought no solution.
I tried changing my movement scripts from FixedUpdate to Update (just in case). Not a solution.
Vsync all 3 optiones (every V blank, every 2 V blank, no sync) didn't fix the issue.
After trying and trying and trying, I came to the conclusion that the issue stems from having the rigidbody's velocity change to 0 from one frame to the next. So I tried changing my movement script to use rigidbody.addforce instead of setting directly my velocity and then apply a force to stop the object. This is the code and it also runs in FixedUpdate()
void FixedUpdate()
{
velocityY = GetComponent<Rigidbody>().velocity.y;
Vector3 currentVelocity = new Vector3 (movesides,0f,moveupdown).normalized;
GetComponent<Rigidbody>().AddForce (currentVelocity.x * currentSpeed * 3f, 0f, currentVelocity.z * currentSpeed);
Vector3 velocity = GetComponent<Rigidbody>().velocity;
if (movesides != 0 && moveupdown == 0)
{
velocity.z = velocity.z * 0.3f;
if (velocity.x >= currentSpeed){
velocity.x = currentSpeed;}
if (velocity.x <= -currentSpeed)
{
velocity.x = -currentSpeed;
}
GetComponent<Rigidbody>().velocity = velocity;
}
if (moveupdown != 0 && movesides == 0)
{
velocity.x = velocity.x * 0.3f;
if (velocity.z >= currentSpeed)
{
velocity.z = currentSpeed;
}
if (velocity.z <= -currentSpeed)
{
velocity.z = -currentSpeed;
}
GetComponent<Rigidbody>().velocity = velocity;
}
if (movesides == 0)
{
velocity.x = velocity.x * 0.3f;
GetComponent<Rigidbody>().velocity = velocity;
}
if (moveupdown == 0)
{
velocity.z = velocity.z * 0.3f;
GetComponent<Rigidbody>().velocity = velocity;
}
And this new script works, no stutter, stops and starts smoothly (its not a finished script, but it's a start). But now i can't go over any edge (like a sidewalk) no matter how small it is. The player gets stuck in every corner if it doesn't already come with speed. If I am already at maximum speed, then I can go over the edge of the sidewalk fine (it just slows down the player a bit), but if I am standing on the edge and press to go over the edge, it doesn't move, probably because it doesn't have momentum to go over the edge.
I love how my rigidbody.velocity script goes over small edges, and I get very smooth starting and endings from the rigidbody.addforce script. I can't seem to join them in one script to be able to get the best of both worlds. It's fine if that's not possible, but at least I need my rigidbody.velocity script (the top one) to stop and start without that jitter/stutter.
My player object has several children.
The root is the GameObject with the rigidbody, a capsule collider and movement script. The rigidbody has gravity checked, is non-kinematic, interpolate set to interpolate and has freeze rotation on all 3 axis.
Inside the root there is an empty game object (lets call it billboard) with a script to always face front (to avoid rotation of my 2d character)
Inside that billboard, there is a Spine Animation Skeleton (the blue sillouette in the gif. The difference of placement of the skeleton when turning is not because of the issue. I'm not flipping the skeleton when going on the opposite direction, its 2 different animations placed slightly off center in Spine.
The issue can be seen when looking at the feet emerging from the sphere (that is the mesh renderer of my root object. And from all my tests, the problem doesn't come from the children Objects, but from the rigidbody itself.
Thank you for your help
If you need more information let me know.
Your answer
Follow this Question
Related Questions
Stop and object from moving faster after a specific speed is reached? 2 Answers
Rigidbody.velocity not moving player 1 Answer
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
3D player blocked by invisible 'Object' 0 Answers