I am having trouble thinking of what the math would be to limit how much velocity I add to my rigidbody.
Here are some examples to better explain my goals
Click for examples
- Example 1-
maxVelocity = 4,0,0
addingVelocity = 2,0,0
myRigidbody.velocity = 3,0,0
goal velocity to add = 1,0,0
- Example 2-
maxVelocity = 4,0,0
addingVelocity = 2,0,0
myRigidbody.velocity = 5,0,0
goal velocity to add = 0,0,0
- Example 3-
maxVelocity = -4,0,0
addingVelocity = -2,0,0
myRigidbody.velocity = 5,0,0
goal velocity to add = -2,0,0
Note - The Mathf.Sign() of the maxVelocity and addingVelocity will always be the same.
My goal is to only add the required amount of velocity to reach the maxVelocity, however, if the rigidbody is already at or above the maxVelocity, then I don’t want to add anything.
Please note that doing Vector3.ClampMagnitude(addingVelocity, maxVelocityMagnitude) is not what I am looking for. That would make it so the addingVelocity does not go over the maxVelocity, but it wont give me the minimum velocity required.
This seems like it should be simple math, but whats getting me is the values signs.
Thank you for any help!
EDIT - Just to try and better explain my goal…
I need to find out how much I can add to move towards my target max velocity.
The maxVelocity is more so the maxVelocityToHave, not the overall max velocity of the rigidbody.
Please keep in mind that I do not know what the goal velocity is. The goal velocity is what we are trying to figure out.
EDIT 2 -
This may be a possible solution, but need to test it.
One big problem this has is it causes you to move faster when going against walls that have no friction.
Click for possible solution
public static void LimitAddRelativeForce(this Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis, ForceMode forceMode)
{
myRigidbody.AddRelativeForce(LimitLocalVelocity(myRigidbody, velocity, maxMagnitude, clampAxis), forceMode);
}
public static void LimitHorizontalAddRelativeForce(this Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, ForceMode forceMode)
{
LimitAddRelativeForce(myRigidbody, velocity, maxMagnitude, new Vector3(1, 0, 1), forceMode);
}
public static Vector3 LimitVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis)
{
Vector3 clampedVelocity = ClampVelocity(myRigidbody, velocity, maxMagnitude, clampAxis);
return LimitVelocity(myRigidbody, velocity, clampedVelocity, maxMagnitude);
}
public static Vector3 LimitLocalVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis)
{
Vector3 clampedVelocity = ClampLocalVelocity(myRigidbody, velocity, maxMagnitude, clampAxis);
return LimitVelocity(myRigidbody, velocity, clampedVelocity, maxMagnitude);
}
static Vector3 LimitVelocity(Rigidbody myRigidbody, Vector3 velocity, Vector3 clampedVelocity, float maxMagnitude)
{
for(int i = 0; i < 3; i++)
{
if(Mathf.Sign(clampedVelocity[i]) == Mathf.Sign(velocity[i]))
{
clampedVelocity[i] = Mathf.Sign(clampedVelocity[i]) * (Mathf.Clamp(Mathf.Abs(clampedVelocity[i]), 0, Mathf.Abs(velocity[i])));
}else{
clampedVelocity[i] = 0;
}
}
return clampedVelocity;
}
public static Vector3 ClampVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis)
{
return Vector3.ClampMagnitude(velocity - myRigidbody.velocity, maxMagnitude).SelectAxis(clampAxis);
}
public static Vector3 ClampLocalVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis)
{
Vector3 clampedVelocity = ClampVelocity(myRigidbody, myRigidbody.transform.TransformDirection(velocity), maxMagnitude, Vector3.one);
return myRigidbody.transform.InverseTransformDirection(clampedVelocity).SelectAxis(clampAxis);
}
public static Vector3 SelectAxis(this Vector3 vector, Vector3 axis)
{
Vector3 selectedAxis = Vector3.zero;
if(axis.x != 0) selectedAxis.x = vector.x;
if(axis.y != 0) selectedAxis.y = vector.y;
if(axis.z != 0) selectedAxis.z = vector.z;
return selectedAxis;
}
The usage looks like this…
Vector3 targetVelocity = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized * force;
myRigidbody.LimitHorizontalAddRelativeForce(targetVelocity, force, ForceMode.VelocityChange);
Other possible solutions (that may need more added to work) are…
Click for other possible solutions
Posted by Todd Wasson
Click for code
Vector3 maxVelocity = velocity.normalized * maxMagnitude;
Vector3 projectedVelocity = myRigidbody.velocity + velocity;
Vector3 difference = Vector3.zero;
if(myRigidbody.velocity.magnitude < maxVelocity.magnitude)
{
if(projectedVelocity.magnitude > maxVelocity.magnitude )
{
difference = projectedVelocity - maxVelocity;
}
}
return velocity - difference;
Posted by hpjohn
Click for code
float maxMagnitude = 4;
Vector3 addVelocity = new Vector3( 1, 0, 2 ); //or whatever from input
Vector3 maxVelocity = addVelocity.normalized * maxMagnitude;
Vector3 currentVelocity = GetComponent<Rigidbody>().velocity;
Vector3 goalVelocity = Vector3.zero;
for ( int i = 0; i < 3; i++ ) {
if ( Mathf.Sign( maxVelocity[i] ) != Mathf.Sign( currentVelocity[i] ) ) {
goalVelocity[i] = Mathf.Min( Mathf.Abs( addVelocity[i] ), Mathf.Abs( maxVelocity[i] ) ) * Mathf.Sign( addVelocity[i] );
} else if ( Mathf.Abs( currentVelocity[i] ) < Mathf.Abs( maxVelocity[i] ) ) {
goalVelocity[i] = Mathf.Min( Mathf.Abs( addVelocity[i] ), Mathf.Abs( maxVelocity[i] - currentVelocity[i] ) ) * Mathf.Sign( addVelocity[i] );
}
}
I posted that below, but decided to bring it up here since most of this thread is just me failing to explain what exactly it is that I am wanting. You can probably skip reading what is below.