Search Unity

How to make rigidbody slow down for a period of time?

Discussion in 'Physics' started by Jeepster, Oct 14, 2019.

  1. Jeepster

    Jeepster

    Joined:
    Jan 23, 2014
    Posts:
    401
    Hi,

    I'm using RigidBody.AddForce to move my player forward, and I've made crates that the player can smash to either gain an advantage or be imposed a dissadvantage, like being forced to move slowly for ten seconds for example.

    I've tried applying massive amounts of Mass, Drag and Angular Drag to the rigid body but it makes little to no difference, since AddForce accelerates over time and the player ends up going just as fast as without these constraints.

    How can I force the player to move slowly for ten seconds, is there an easy way to impose something on the rigid body that makes it move slower without disabling the movement script altogether for a while?
     
  2. Maeslezo

    Maeslezo

    Joined:
    Jun 16, 2015
    Posts:
    331
    Maybe time scale?

    https://docs.unity3d.com/ScriptReference/Time-timeScale.html
     
  3. canis

    canis

    Joined:
    Oct 25, 2013
    Posts:
    79
    Are you sure your movement script are moved by rigidbody addForce ???
    in that case..
    you need to limit the player movement force during this session (Obvious).

    however another problem is deal with the exist force & apply the new force at the same time.
    see if you can understand the following example. >> Line 35~38
    those are the way to correctly apply neutralize force to slow down the object.

    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3. [RequireComponent(typeof(Rigidbody))]
    4. public class TestPhy : MonoBehaviour
    5. {
    6.     public Rigidbody m_Rigidbody;
    7.     public bool m_EnableNoiseFromPlayer = true;
    8.     private void Awake()
    9.     {
    10.         // Demo usage.
    11.         if (m_Rigidbody == null)
    12.             m_Rigidbody = GetComponent<Rigidbody>();
    13.         m_Rigidbody.useGravity = false;
    14.     }
    15.  
    16.     private void OnEnable()
    17.     {
    18.         StartCoroutine(BreakInSecond(Random.Range(1f, 5f), Random.Range(3, 5)));
    19.         StartCoroutine(PlayerInputSimulater());
    20.     }
    21.  
    22.     private IEnumerator BreakInSecond(float delay, int sec)
    23.     {
    24.         float power = Random.Range(4, 8);
    25.         m_Rigidbody.AddForce(Random.insideUnitSphere * power, ForceMode.Impulse);
    26.         Debug.Log($"Object launch power {power:F1}, delay : {delay:F1}");
    27.  
    28.         yield return new WaitForSeconds(delay);
    29.         Debug.Log($"Start break in second {sec}");
    30.         const float breakRadio = .5f;
    31.         int i = sec;
    32.         while (i-- > 0)
    33.         {
    34.             Debug.Log($"ETA - {i}/{sec}");
    35.             Vector3 reduceForce =
    36.                 m_Rigidbody.velocity * // current velocity
    37.                 breakRadio * // the percentage to slow down
    38.                 -1f; // flip the vector to neutralize the velocity.
    39.             m_Rigidbody.AddForce(reduceForce, ForceMode.VelocityChange);
    40.             yield return new WaitForSeconds(1f);
    41.         }
    42.  
    43.         m_EnableNoiseFromPlayer = false;
    44.         // STOP : this is how you stop it.
    45.         Vector3 reverseForce = -m_Rigidbody.velocity; // include gravity.
    46.         m_Rigidbody.AddForce(reverseForce, ForceMode.VelocityChange);
    47.         Debug.Log($"Object stopped.");
    48.     }
    49.  
    50.     private IEnumerator PlayerInputSimulater()
    51.     {
    52.         while (true)
    53.         {
    54.             if (m_EnableNoiseFromPlayer && Random.value > 0.5f)
    55.             {
    56.                 Vector3 simulatePlayerInput = Random.insideUnitSphere;
    57.                 Debug.DrawRay(transform.position, simulatePlayerInput, Color.red, 3f, true);
    58.                 m_Rigidbody.AddForce(simulatePlayerInput, ForceMode.Impulse);
    59.             }
    60.             yield return new WaitForSeconds(.3f);
    61.         }
    62.     }
    63. }
     
  4. Jeepster

    Jeepster

    Joined:
    Jan 23, 2014
    Posts:
    401
    So flipping the vector and countering the force is the only way? I was hoping for a rigid body function that I didn't know about.

    And yes, of course I'm sure I'm using AddForce to move my player :D
     
  5. Ruchir

    Ruchir

    Joined:
    May 26, 2015
    Posts:
    934
    You can use the ForceMode.VelocityChange mode in AddForce function to limit your players velocity
     
    swingingtom and Jeepster like this.
  6. Jeepster

    Jeepster

    Joined:
    Jan 23, 2014
    Posts:
    401
    That's exactly what I was looking for. Thank you so much!