Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Moving Player Character via RigidBody

Discussion in 'Scripting' started by UnityGuy1988, Sep 29, 2023.

  1. UnityGuy1988

    UnityGuy1988

    Joined:
    Jan 12, 2020
    Posts:
    24
    I'm trying to move my player model using a method involving its Rigidbody in the FixedUpdate method as I'm told that it is the way to go for games where physics and collisions are involved. Until now I've been using the classic transform.Translate method and using a controller stick input to dictate the rate of movement. The thing with using the Rigidbody is that if you use a method like AddForce it seems to me has a cumulative effect (as in, it adds a certain amount of force or velocity each step, depending on the 'Forcemode'). This causes the character to gain more and more speed every frame and whizz off the side of the world. On the other hand, if you modify the velocity per step in Rigidbody.velocity, it responds to a Vector3 input relative to the world coordinates, rather than using the player forward direction. Is there a way to either modify a Vector3 so it is relative to the player's forward direction, or alternatively, a way to use Rigidbody.AddForce such that you can prevent the object from exceeding a certain speed? With the tranform.Translate method I've been using, the velocity is defined by the controller input alone, so perhaps adding a sense of inertia through adding acceleration and then capping the maximum velocity (somehow!) would be the best thing to do?
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    3,721
    Typically a physics-based character controller has IsKinematic set to true so it won't react to external forces. In kinematic mode you set the velocity of the rigidbody directly.

    If that's not the kind of character you want, for example a ball rolling over the world that should behave physically correct, you can try setting other force modes of the AddForce method.

    Note that there's also a cool but advanced Kinematic Character Controller on the Asset Store that's free (the dev now works for Unity).
     
    UnityGuy1988 likes this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,283
    With Physics (or Physics2D), never manipulate the Transform directly. If you manipulate the Transform directly, you are bypassing the physics system and you can reasonably expect glitching and missed collisions and other physics mayhem.

    This means you may not change transform.position, transform.rotation, you may not call transform.Translate(), transform.Rotate() or other such methods, and also transform.localScale is off limits. You also cannot set rigidbody.position or rigidbody.rotation directly. These ALL bypass physics.

    Always use the .MovePosition() and .MoveRotation() methods on the Rigidbody (or Rigidbody2D) instance in order to move or rotate things. Doing this keeps the physics system informed about what is going on.

    https://forum.unity.com/threads/col...-unity-physic-rigidbody.1216875/#post-7763061

    https://forum.unity.com/threads/oncollisionenter2d-not-being-called.1266563/#post-8044121

    If you want to see what is easily possible with just a little bit of scripting around a basic Rigidbody setup, check out what this guy pulled off in Very Very Valet:

     
    UnityGuy1988 likes this.
  4. zulo3d

    zulo3d

    Joined:
    Feb 18, 2023
    Posts:
    421
    To prevent a rigidbody from gaining too much speed from AddForce you need to set the drag property.
     
    UnityGuy1988 likes this.
  5. UnityGuy1988

    UnityGuy1988

    Joined:
    Jan 12, 2020
    Posts:
    24
    Thanks for the info, I'll check out that link. My game involves a character pushing a ball around, I noticed some stuttery motion when I do so, could this be due to the ball affecting the physics of the character? Might it be that I need to turn IsKinematic on for the player character? If I do so, can I then disable IsKinematic when the character collides with something I do want to affect its physics?

    Thanks for the info. I wasn't aware of the MovePosition or MoveRotation methods, seems like it would be a good idea, except for the fact that MovePosition takes a Vector3 value, and moves the character relative to world coordinates ('Pacman' style movement). I need more of a 3rd person style movement control, is there a way to do the same thing only relative to the player's orientation? Thanks for the link by the way, very interesting!

    Not sure if that's the way to go, as I'm trying to move my player character, not a projectile!
     
  6. UnityGuy1988

    UnityGuy1988

    Joined:
    Jan 12, 2020
    Posts:
    24
    I've figured out the issue with the movement relative to the player's rotation. Apparently, the solution is to multiply the Vector3 input by the Rigidbody.rotation. Not sure how that works, can anybody explain that to me, or is there any source of information out there?
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,283
    Multiplying a Vector3 by a Quaternion will rotate the Vector3... by that Quaternion!

    That should give you plenty of googling material.

    All about Euler angles and rotations, by StarManta:

    https://starmanta.gitbooks.io/unitytipsredux/content/second-question.html
     
    UnityGuy1988 likes this.
  8. UnityGuy1988

    UnityGuy1988

    Joined:
    Jan 12, 2020
    Posts:
    24
  9. Elhimp

    Elhimp

    Joined:
    Jan 6, 2013
    Posts:
    71
    Instead of setting velocity to some value, you need to find how much force you need to add to get body from current velocity to target one. Most basic equation looks like this:
    Code (CSharp):
    1. float deltaForce = Mathf.Clamp((desiredVelocity - currentVelocity) * m, -acceleration, acceleration);
    Set drag to 0, use ForceMode.Acceleration to avoid mass correction,
    m
    is how hard object pushed. Values lower than 1.0 makes movement floaty, and larger than 4.0 creates slight overshoot. And
    acceleration
    speaks for itself.

    1. Now, as you've been told, you can get current velocity in object relative space
    https://docs.unity3d.com/ScriptReference/Quaternion.Inverse.html
    or
    https://docs.unity3d.com/ScriptReference/Transform.InverseTransformDirection.html

    2. Get the difference for each vector component

    3. And then apply it
    https://docs.unity3d.com/ScriptReference/Rigidbody.AddRelativeForce.html