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?
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.
using System.Collections;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class TestPhy : MonoBehaviour
{
public Rigidbody m_Rigidbody;
public bool m_EnableNoiseFromPlayer = true;
private void Awake()
{
// Demo usage.
if (m_Rigidbody == null)
m_Rigidbody = GetComponent<Rigidbody>();
m_Rigidbody.useGravity = false;
}
private void OnEnable()
{
StartCoroutine(BreakInSecond(Random.Range(1f, 5f), Random.Range(3, 5)));
StartCoroutine(PlayerInputSimulater());
}
private IEnumerator BreakInSecond(float delay, int sec)
{
float power = Random.Range(4, 8);
m_Rigidbody.AddForce(Random.insideUnitSphere * power, ForceMode.Impulse);
Debug.Log($"Object launch power {power:F1}, delay : {delay:F1}");
yield return new WaitForSeconds(delay);
Debug.Log($"Start break in second {sec}");
const float breakRadio = .5f;
int i = sec;
while (i-- > 0)
{
Debug.Log($"ETA - {i}/{sec}");
Vector3 reduceForce =
m_Rigidbody.velocity * // current velocity
breakRadio * // the percentage to slow down
-1f; // flip the vector to neutralize the velocity.
m_Rigidbody.AddForce(reduceForce, ForceMode.VelocityChange);
yield return new WaitForSeconds(1f);
}
m_EnableNoiseFromPlayer = false;
// STOP : this is how you stop it.
Vector3 reverseForce = -m_Rigidbody.velocity; // include gravity.
m_Rigidbody.AddForce(reverseForce, ForceMode.VelocityChange);
Debug.Log($"Object stopped.");
}
private IEnumerator PlayerInputSimulater()
{
while (true)
{
if (m_EnableNoiseFromPlayer && Random.value > 0.5f)
{
Vector3 simulatePlayerInput = Random.insideUnitSphere;
Debug.DrawRay(transform.position, simulatePlayerInput, Color.red, 3f, true);
m_Rigidbody.AddForce(simulatePlayerInput, ForceMode.Impulse);
}
yield return new WaitForSeconds(.3f);
}
}
}