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

ClampMagnitude -- why no minimum?

Discussion in 'Scripting' started by MV10, Feb 26, 2016.

  1. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    I'm applying both positive and negative forces to a rigidbody, but I need a minimum and maximum speed.
    ClampMagnitude allows me to specify a maximum, but not a minimum.

    Is there a reason for this?

    It's easy enough to do it myself, of course, I'm just curious.

    Code (csharp):
    1. if (rigidbody.velocity.magnitude < minVelocity) rigidbody.velocity = rigidbody.velocity.normalized * minVelocity;
    I assume internally ClampMagnitude does exactly this but using a greater-than operator.
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,376
    First, here's ClampMagnitude:
    Code (csharp):
    1.  
    2.     /// <summary>
    3.     ///
    4.     /// <para>
    5.     /// Returns a copy of vector with its magnitude clamped to maxLength.
    6.     /// </para>
    7.     ///
    8.     /// </summary>
    9.     /// <param name="vector"/><param name="maxLength"/>
    10.     public static Vector3 ClampMagnitude(Vector3 vector, float maxLength)
    11.     {
    12.       if ((double) vector.sqrMagnitude > (double) maxLength * (double) maxLength)
    13.         return vector.normalized * maxLength;
    14.       return vector;
    15.     }
    16.  
    Note, it uses sqrMagnitude because it's faster.

    As for why it's only has the max... who knows. Unity engineers probably just didn't bother to put it in.

    Why do they clamp lerps to a t value of 0->1, and then have an 'LerpUnclamped'?

    They make weird decisions for their own reasons.

    Write a custom 'ClampMagnitude' that accepts both a min and a max...

    Code (csharp):
    1.  
    2. public static Vector3 ClampMagnitude(Vector3 v, float max, float min)
    3. {
    4.     double sm = v.sqrMagnitude;
    5.     if(sm > (double)max * (double)max) return v.normalized * max;
    6.     else if(sm < (double)min * (double)min) return v.normalized * min;
    7.     return v;
    8. }
    9.  
     
    bomdiaJJ, Bunny83, er1227 and 5 others like this.
  3. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    Yeah I did write my own, though this n00b often forgets sqrMagnitude.
     
  4. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    Maybe I have actually stumbled into an explanation (although it's probably just coincidence).

    I'm clamping the magnitude of a Rigidbody's velocity in a system which applies positive and negative values for AddForce. These forces should (in theory) bring the forward vector into alignment with the velocity vector, and also to reduce forward motion when the object is changing direction. In this particular case, clamping the maximum is always ok, but blindly clamping the minimum means the Rigidbody can't reverse direction. Reversing direction is necessary when the velocity vector is more than 180 degrees out of alignment with the forward vector (e.g. the object ends up moving backwards), as can happen immediately after extremely sharp turns. My current approach is to clamp the minimum only when the forward and velocity vectors are aligned in a forward direction (dot product > 0).

    I suppose it's unlikely that this narrow case would be the reason for the API to only clamp the maximum, but I can see how a blanket clamp on the minimum could cause trouble from time to time, whereas a maximum clamp is probably fairly foolproof.

    The Lerp clamp makes plenty of sense to me. It goes without saying that interpolation doesn't work without a known range and a percentage (float 0-to-1) is an obvious and simple way to generically represent progress over any range of values, especially in the "floats everywhere" world of Unity...
     
  5. WARW0LF

    WARW0LF

    Joined:
    Oct 1, 2016
    Posts:
    15
    old but still thank you, this was doing my head in, i couldn't figure out how to set a min for it
     
  6. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    464
    since this thread is already resurrected I guess I could also throw in my opinion for why ClampMagnitude doesn't have a "min" value: There is no reasonable answer to what ClampMagnitude should output if the input Vector3 is (0,0,0).
     
    lordofduct likes this.
  7. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,735
    While true, this is also true for many other methods involving vectors, such as .Normalize() or Quaternion.LookRotation().
     
    tjmaul likes this.