Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Help understanding RigidBody.AddForce()

Discussion in 'Physics' started by unity_cRmZ8becPmhu2g, Jun 1, 2019.

  1. unity_cRmZ8becPmhu2g

    unity_cRmZ8becPmhu2g

    Joined:
    Mar 22, 2019
    Posts:
    1
    I just start diving into creating my own FPS controller and have gotten hung up on an issue with using AddForce() while trying to implement a walk/run system. In the below code I have two values maxWalkSpeed and maxRunSpeed which I am using to change the magnitude of the force vector passed to AddForce() if keyRun is pressed. I have verified in the debugger that when keyRun is pressed I get into the expected if(isRunning) case seen in the Move().

    The issue I am seeing is that there appears to be a difference in how AddForce() behaves between compile time parameter changes and run time changes. To give a step-by-step of what I mean:
    1. Starting with the values seen in the code below I run my game and press the W key to move forward. My RigidBody accelerates to a constant speed as expected. Using the debugger to look at targetVel I see that since keyRun is not pressed targetVel = (0, 0, 25.0)
    2. Now pressing keyRun and inspecting targetVel I see that it changes as expected to (0, 0, 50.0) but despite this the speed of my RigidBody does not increase
    3. Pausing the game I now change maxWalkSpeed to be 50 (same as maxRunSpeed) and restart the game inspecting targetVel while holding W and the debugger now shows that it is (0, 0, 50.0), the same as in Step 2, but I now see my RigidBody moving noticeably faster compared to Step 1
    So far googling hasn't helped me come up with an explanation for this behavior. It would seem to me that I should be able to change the vector passed to AddForce at anytime and (assuming my force values can move my RigidBody) see a resulting change velocity but since I don't see this expected behavior I feel I have some misunderstanding as to what exactly AddForce() is doing.

    Code:
    Code (CSharp):
    1. public class PlayerMovement : MonoBehaviour
    2. {
    3. //Public Variables
    4.     //Camera
    5.     public Camera fpsCamera;
    6.  
    7.     //Input Keys
    8.     public KeyCode keyRun;
    9.     public KeyCode keyCrouch;
    10.     public KeyCode keyJump;
    11.     public KeyCode keyClimb;
    12.  
    13.     //Movement Settings
    14.     public float maxWalkSpeed = 25.0f;
    15.     public float maxRunSpeed = 50.0f;
    16.     public float movementAccel = 10000.0f;
    17.     public float movementDecel = 10000.0f;
    18.  
    19.  
    20.     //Private Variables
    21.  
    22.     //Player Components
    23.     private Rigidbody playerRgbd;
    24.     private CapsuleCollider playerCapsule;
    25.  
    26.     //Input
    27.     private float inputX;
    28.     private float inputY;
    29.  
    30.     //Movement
    31.     private Vector3 movement;
    32.  
    33.     private bool isRunning = false;
    34.  
    35. //Unity Functions
    36.     // Start is called before the first frame update
    37.     void Start()
    38.     {
    39.         if(GetComponent<Rigidbody>())
    40.             playerRgbd = GetComponent<Rigidbody>();
    41.         if(GetComponent<CapsuleCollider>())
    42.             playerCapsule = GetComponent<CapsuleCollider>();
    43.  
    44.         Cursor.lockState = CursorLockMode.Locked;
    45.     }
    46.  
    47.     // Update is called once per frame
    48.     void Update()
    49.     {
    50.  
    51.         InputManagement();
    52.     }
    53.  
    54.     private void FixedUpdate()
    55.     {
    56.         Move(inputX, inputY);
    57.     }
    58.  
    59. //Custom Functions
    60.     private void InputManagement()
    61.     {
    62.         if (Input.GetKeyDown(keyRun))
    63.             isRunning = true;
    64.         else
    65.             isRunning = false;
    66.        
    67.     }
    68.  
    69.     private void Move(float h, float v)
    70.     {
    71.         Vector3 targetVel;
    72.         Vector3 accelDir = ((h * transform.right) + (v * transform.forward)).normalized;
    73.  
    74.         inputX = Input.GetAxisRaw("Horizontal");
    75.         inputY = Input.GetAxisRaw("Vertical");
    76.  
    77.         if (v != 0 || h != 0)
    78.         {
    79.             if (isRunning)
    80.                 targetVel = maxRunSpeed * accelDir;
    81.             else
    82.                 targetVel = maxWalkSpeed * accelDir;
    83.             AccelerateTo(playerRgbd, targetVel, movementAccel);
    84.         }
    85.         else
    86.         {
    87.             targetVel = Vector3.zero;
    88.             AccelerateTo(playerRgbd, targetVel, movementDecel);
    89.         }
    90.     }
    91.  
    92.     private void AccelerateTo(Rigidbody body, Vector3 targetVelocity, float maxAccel)
    93.     {
    94.         Vector3 deltaV = targetVelocity - body.velocity;
    95.         Vector3 accel = deltaV / Time.deltaTime;
    96.  
    97.         if (accel.sqrMagnitude > maxAccel * maxAccel)
    98.             accel = accel.normalized * maxAccel;
    99.  
    100.         body.AddForce(accel, ForceMode.Acceleration);
    101.     }
    102. }