0
\$\begingroup\$

I'm playing around with Unity, trying to make a neat 3rd person platformer movement system using rigidbodies so that I may in the future implement things like pushing boxes/physics objects, grappling hooks, etc... as well as I'm not really knowledgeable in terms of math and physics to be able to code them from scratch using CharacterController

What I've done is I've implemented some basic movement by setting velocity directly

Vector2 input = GetInput();
bool hasInput = Mathf.Abs(input.x) > float.Epsilon || Mathf.Abs(input.y) > float.Epsilon;
bool isDashing = dashCounter > 0f;
if (hasInput && !isDashing)
{
    Vector3 direction = GetDirection(); // get camera direction scaled by forward & right vectors
    transform.localRotation = Quaternion.LookRotation(direction);

    UpdateTargetSpeed(input); // update target speed based on movement direction
    Vector3 movementVector = new Vector3(input.x * TargetSpeed, 0f, input.y * TargetSpeed); // add speed to input vector
    movementVector = transform.localRotation * movementVector; // rotate the vector to where the character is facing
    movementVector = Vector3.ClampMagnitude(movementVector, TargetSpeed); // clamp magnitude to avoid faster speed on diagonals            

    body.velocity = new Vector3(movementVector.x, Velocity.y, movementVector.z);
}

And I'm also projecting velocity on ground normal for slopes so that the character doesn't fly off when moving down slopes

if (wasPreviouslyGrounded && !jumping && groundCheck.CanStick)
{
    float slopeAngle = Mathf.Abs(Vector3.Angle(groundCheck.StickyContactNormal, Vector3.up));                
    if (slopeAngle < 85f)
    {
        body.velocity = Vector3.ProjectOnPlane(Velocity, groundCheck.StickyContactNormal);
    }
}

I have implemented jumping and dashing using AddForce

body.AddForce(0f, movementSettings.JumpForce, 0f, ForceMode.Impulse);

This all works okay but everywhere I looked people are always claiming that setting velocity directly is a bad practice and should be avoided. I've seen suggestions to use AddForce instead, but I haven't been able to get the same movement with it, no matter which force mode I used. I am also lost on how to control the amount of force I'm giving to the body during continuous movement. The thing I did is to check the magnitude of body's current velocity and if it's at or above the target speed then forgo applying the force but that just makes the body continuously accelerate and decelerate giving off jittery movement

if (body.velocity.sqrMagnitude < TargetSpeed * TargetSpeed)
{
    body.AddForce(force, ForceMode.VelocityChange);
}

Can anyone ELI5 me the answers to the following questions:

  1. Why exactly is setting velocity directly a "bad practice"?
  2. What is the preferred alternative?
  3. How can I get snappy and responsive movement without setting the velocity directly?
  4. How can I accomplish sticking to the ground when going down slopes without projecting and setting the velocity directly?
\$\endgroup\$
  • \$\begingroup\$ I have an older answer about this here, which may answer several of your points. Is anything still unclear after reading that? \$\endgroup\$ – DMGregory Oct 21 '20 at 15:00
  • \$\begingroup\$ i think faking collisions by setting velocity is bad, but setting velocity for objects which naturally move by themselves is ok; although you have a case when something is blocking the elevator still unsolved \$\endgroup\$ – ivan866 Oct 21 '20 at 15:41
  • \$\begingroup\$ @DMGregory thanks for the link. It did help quite a bit in helping me understand why setting velocity directly is not such a good idea. Now that I've read that I do have a couple of additional questions. I've updated the OP with them. \$\endgroup\$ – MrPlow Oct 21 '20 at 21:56
  • \$\begingroup\$ I recommend posting your new questions as a new Question post, as they depart from the topic covered by the answer Philipp provided below. Once a post has an answer, it's best to limit edits to clarifying the initial topic, rather than expanding it to encompass new topics. \$\endgroup\$ – DMGregory Oct 21 '20 at 22:01
  • \$\begingroup\$ @DMGregory okay. I will do that \$\endgroup\$ – MrPlow Oct 22 '20 at 14:25
1
\$\begingroup\$

When you set the velocity of your rigidbody directly, then:

  • It will (obviously) cancel all other forces acting on the rigidbody. So you lose the option to use any force-based effects at all on this object. That means no knockback, no explosions, no wind... (unless you program the low-level physics for those yourself)
  • When there are other non-kinematic non-static rigidbodies blocking the object's path, then the physics engine will give it as much force as it needs to push them away without slowing down. Applying potentially unlimited forces in rigidbody-collisions can cause potentially unlimited physics glitches. You might witness "fun" game mechanics like rigibodies getting launched into orbit or getting pushed through solid walls.

So unless you want no actual rigidbody physics at all in your game, always move objects by using AddForce.

When you have the problem that your object acts as if it's sliding on ice (not snappy and responsive), then crank up the "Drag" setting of the rigidbody. It will result in a shorter acceleration and deceleration and also put a limit on how fast it can get. But you will also need more force to achieve the same speed.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.