Reputation: 21
I am working on a player controller and having trouble with limiting the character's velocity. The character seems to accelerate indefinitely.
I am updating the character's velocity using rb.AddForce(movement * movementSpeed, ForceMode.VelocityChange)
, where movement
is a normalized Vector3
(with values only for x
and z
) and movementSpeed
is a public float giving the desired movement speed. I realize that it would be trivial to cap the character's velocity by setting it directly but I'm under the impression that setting rb.velocity
directly is bad practice (which I'm not entirely sure is true).
My fixed update function:
private void FixedUpdate()
{
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
movement.Normalize();
rb.AddForce(movement * movementForce, ForceMode.VelocityChange);
}
I have tried adding a conditional statement checking if the velocity is greater than the desired maximum and, if true, adding a force in the opposing direction. This results in stuttering. The character's velocity is reset to 0 and forced to accelerate again.
Vector3 currMovement = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
float currMagnitude = currMovement.magnitude;
if (currMagnitude > movementSpeed) {
rb.AddForce(currMovement * (-1 * movementSpeed / currMagnitude), ForceMode.VelocityChange);
}
Any help would be greatly appreciated?
rb.AddForce(movement, ForceMode.VelocityChange)
?rb.AddForce
or can I directly set rb.velocity
?Upvotes: 0
Views: 3595
Reputation: 1529
I don't see anything wrong with setting the velocity directly, especially when it comes to capping velocity. I think people tend to visualize velocity better when they're adding a force in a direction rather than directly setting it, but no, in short, I don't think it's bad practice.
Have a look at Unity's Mathf.Clamp documentation. I'd do something like:
private void FixedUpdate()
{
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
movement.Normalize();
rb.AddForce(movement * movementForce, ForceMode.VelocityChange);
rb.velocity = new Vector3(Mathf.Clamp(rb.velocity.x, -SomeMaximumVelocity, SomeMaximumVelocity),
rb.velocity.y,
Mathf.Clamp(rb.velocity.z, -SomeMaximumVelocity, SomeMaximumVelocity));
}
Upvotes: 0