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

[Possibly Solved] Math problem for limiting a rigidbodies velocity

Discussion in 'Scripting' started by HiddenMonk, Jul 1, 2015.

  1. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    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
    - 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.
    Code (CSharp):
    1.     public static void LimitAddRelativeForce(this Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis, ForceMode forceMode)
    2.     {
    3.         myRigidbody.AddRelativeForce(LimitLocalVelocity(myRigidbody, velocity, maxMagnitude, clampAxis), forceMode);
    4.     }
    5.  
    6.     public static void LimitHorizontalAddRelativeForce(this Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, ForceMode forceMode)
    7.     {
    8.         LimitAddRelativeForce(myRigidbody, velocity, maxMagnitude, new Vector3(1, 0, 1), forceMode);
    9.     }
    Code (CSharp):
    1.     public static Vector3 LimitVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis)
    2.     {
    3.         Vector3 clampedVelocity = ClampVelocity(myRigidbody, velocity, maxMagnitude, clampAxis);
    4.         return LimitVelocity(myRigidbody, velocity, clampedVelocity, maxMagnitude);
    5.     }
    6.     public static Vector3 LimitLocalVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis)
    7.     {
    8.         Vector3 clampedVelocity = ClampLocalVelocity(myRigidbody, velocity, maxMagnitude, clampAxis);
    9.         return LimitVelocity(myRigidbody, velocity, clampedVelocity, maxMagnitude);
    10.     }
    11.     static Vector3 LimitVelocity(Rigidbody myRigidbody, Vector3 velocity, Vector3 clampedVelocity, float maxMagnitude)
    12.     {
    13.         for(int i = 0; i < 3; i++)
    14.         {
    15.             if(Mathf.Sign(clampedVelocity[i]) == Mathf.Sign(velocity[i]))
    16.             {
    17.                 clampedVelocity[i] = Mathf.Sign(clampedVelocity[i]) * (Mathf.Clamp(Mathf.Abs(clampedVelocity[i]), 0, Mathf.Abs(velocity[i])));
    18.             }else{
    19.                 clampedVelocity[i] = 0;
    20.             }
    21.         }
    22.         return clampedVelocity;
    23.     }
    Code (CSharp):
    1.     public static Vector3 ClampVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis)
    2.     {
    3.         return Vector3.ClampMagnitude(velocity - myRigidbody.velocity, maxMagnitude).SelectAxis(clampAxis);
    4.     }
    5.  
    6.     public static Vector3 ClampLocalVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis)
    7.     {
    8.         Vector3 clampedVelocity = ClampVelocity(myRigidbody, myRigidbody.transform.TransformDirection(velocity), maxMagnitude, Vector3.one);
    9.         return myRigidbody.transform.InverseTransformDirection(clampedVelocity).SelectAxis(clampAxis);
    10.     }
    Code (CSharp):
    1.     public static Vector3 SelectAxis(this Vector3 vector, Vector3 axis)
    2.     {
    3.         Vector3 selectedAxis = Vector3.zero;
    4.         if(axis.x != 0) selectedAxis.x = vector.x;
    5.         if(axis.y != 0) selectedAxis.y = vector.y;
    6.         if(axis.z != 0) selectedAxis.z = vector.z;
    7.  
    8.         return selectedAxis;
    9.     }

    The usage looks like this...
    Code (CSharp):
    1. Vector3 targetVelocity = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized * force;
    2. myRigidbody.LimitHorizontalAddRelativeForce(targetVelocity, force, ForceMode.VelocityChange);

    Other possible solutions (that may need more added to work) are...
    Posted by Todd Wasson
    Code (CSharp):
    1.         Vector3 maxVelocity = velocity.normalized * maxMagnitude;
    2.         Vector3 projectedVelocity = myRigidbody.velocity + velocity;
    3.         Vector3 difference = Vector3.zero;
    4.  
    5.         if(myRigidbody.velocity.magnitude < maxVelocity.magnitude)
    6.         {
    7.             if(projectedVelocity.magnitude > maxVelocity.magnitude )
    8.             {
    9.                difference = projectedVelocity - maxVelocity;
    10.             }
    11.         }
    12.         return velocity - difference;

    Posted by hpjohn
    Code (CSharp):
    1.         float maxMagnitude = 4;
    2.         Vector3 addVelocity = new Vector3( 1, 0, 2 ); //or whatever from input
    3.         Vector3 maxVelocity = addVelocity.normalized * maxMagnitude;
    4.         Vector3 currentVelocity = GetComponent<Rigidbody>().velocity;
    5.  
    6.         Vector3 goalVelocity = Vector3.zero;
    7.  
    8.         for ( int i = 0; i < 3; i++ ) {
    9.             if ( Mathf.Sign( maxVelocity[i] ) != Mathf.Sign( currentVelocity[i] ) ) {
    10.                 goalVelocity[i] = Mathf.Min( Mathf.Abs( addVelocity[i] ), Mathf.Abs( maxVelocity[i] ) ) * Mathf.Sign( addVelocity[i] );
    11.             } else if ( Mathf.Abs( currentVelocity[i] ) < Mathf.Abs( maxVelocity[i] ) ) {
    12.                 goalVelocity[i] = Mathf.Min( Mathf.Abs( addVelocity[i] ), Mathf.Abs( maxVelocity[i] - currentVelocity[i] ) ) * Mathf.Sign( addVelocity[i] );
    13.             }
    14.         }
    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.
     
    Last edited: Jul 5, 2015
  2. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    are those values supposed to represent local or world velocity?
     
  3. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    It will be world since myRigidbody.velocity is world. Local space conversions are done beforehand for the addingVelocity.
    In other words, dont worry about the vectors space.
     
  4. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    Not sure if it's a good idea to be adding the velocity directly like this instead of using forces and letting the physics take care of it, but if that's what you want to do, here's how I'd go about it:

    What I'd try doing first is computing the velocity it would attain without any limit (I'll call it projectedVelocity). Then just do a subtraction to pop the projectedVelocity to the maxVelocity. If you don't mind using an if() statement, something like this might work (untested, just doing this off the top of my head):

    Code (csharp):
    1.  
    2. //Using your variables
    3. //Given:
    4. Vector3 maxVelocity = ...;
    5. Vector3 addingVelocity = ...;
    6. myRigidbody.velocity = ....;
    7.  
    8. //New variables:
    9. Vector3 projectedVelocity = myRigidbody.velocity + addingVelocity;
    10. Vector3 difference = Vector3.zero;
    11.  
    12. //A couple of different ways for limiting the velocity come to mind that concern the direction of the final velocity vector.
    13. //Probably the easiest way with this approach would be to make sure the final velocity is pointed in the same direction as it would be if the velocity were unrestricted.
    14. //So you're letting the direction change as it would without the maxVelocity restriction, but then scaling back the velocity:
    15.  
    16. if(projectedVelocity.magnitude > maxVelocity.magnitude)
    17. {
    18.     difference = projectedVelocity - maxVelocity;
    19. }
    20.  
    21. Vector3 goalVelocityToAdd = addingVelocity - difference;
    22.  
    23.  
    When thinking about this stuff I visualize 3D vectors instead of thinking about it component by component where signs get confusing. When you're trying to cap a vector, you just create a new vector that joins the head of one to the tail of the other by subtracting them to get the difference.
     
    Last edited: Jul 2, 2015
  5. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
  6. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    I will be using AddForce with a ForceMode of VelocityChange, not changing the velocity directly.

    If my math is correct, I think your code is not the answer I need.

    Lets take my first 2 examples.
    - Example 1-
    maxVelocity = 4,0,0
    addingVelocity = 2,0,0
    myRigidbody.velocity = 3,0,0

    goal velocity to add = 1,0,0

    Code (CSharp):
    1. Vector3 projectedVelocity = 5,0,0; // 3,0,0 + 2,0,0
    2. Vector3 difference = Vector3.zero;
    3.  
    4. if(5 > 4) // it is
    5. {
    6.     difference = 1; //5 - 4
    7. }
    8.  
    9. Vector3 goalVelocityToAdd = 1,0,0; // 2,0,0 - 1,0,0
    All seems fine here.

    - Example 2-
    maxVelocity = 4,0,0
    addingVelocity = 2,0,0
    myRigidbody.velocity = 5,0,0

    goal velocity to add = 0,0,0

    Code (CSharp):
    1. Vector3 projectedVelocity = 7,0,0; // 5,0,0 + 2,0,0
    2. Vector3 difference = Vector3.zero;
    3.  
    4. if(7 > 4) // it is
    5. {
    6.     difference = 3; //7 - 4
    7. }
    8.  
    9. Vector3 goalVelocityToAdd = -1,0,0; // 2,0,0 - 3,0,0
    Goal velocity was not reached, I do not want to add in an opposite direction to make it go slower.

    Here is a hackish attempt I did that does not work, but maybe it can spark some ideas.
    I think the part that does not work is the part where the signs of the velocity is not the same with the signs of the rigidbody.velocity.
    Code (CSharp):
    1.     public static Vector3 LimitVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude)
    2.     {
    3.         Vector3 maxVelocity = velocity.normalized * maxMagnitude;
    4.         Vector3 squaredVelocity = Vector3.Scale(velocity, velocity);
    5.         Vector3 squaredRigidbodyVelocity = Vector3.Scale(myRigidbody.velocity, myRigidbody.velocity);
    6.         Vector3 squaredMaxVelocity = Vector3.Scale(maxVelocity, maxVelocity);
    7.  
    8.         float[] limitedVelocityValues = new float[3];
    9.  
    10.         for(int i = 0; i < limitedVelocityValues.Length; i++)
    11.         {
    12.             if(Mathf.Sign(velocity.SelectAxis(i)) == Mathf.Sign(myRigidbody.velocity.SelectAxis(i)))
    13.             {
    14.                 if(Mathf.Abs(velocity.SelectAxis(i)) + Mathf.Abs(myRigidbody.velocity.SelectAxis(i)) < Mathf.Abs(maxVelocity.SelectAxis(i)))
    15.                 {
    16.                     limitedVelocityValues[i] = velocity.SelectAxis(i);
    17.                 }else{
    18.                     float x = Mathf.Abs(maxVelocity.SelectAxis(i)) - Mathf.Abs(myRigidbody.velocity.SelectAxis(i));
    19.                     limitedVelocityValues[i] = (x > 0) ? x : 0;
    20.                 }
    21.             }else{
    22.                 if(squaredVelocity.SelectAxis(i) - squaredRigidbodyVelocity.SelectAxis(i) <= squaredMaxVelocity.SelectAxis(i))
    23.                 {
    24.                     limitedVelocityValues[i] = velocity.SelectAxis(i);
    25.                 }else{
    26.                     limitedVelocityValues[i] = maxVelocity.SelectAxis(i) - myRigidbody.velocity.SelectAxis(i);
    27.                 }
    28.             }
    29.         }
    30.  
    31.         return new Vector3(limitedVelocityValues[0], limitedVelocityValues[1], limitedVelocityValues[2]);
    32.     }
     
    Last edited: Jul 2, 2015
  7. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    Oh, right, I see what you mean. I wasn't thinking about case 2. Would this work instead?
    Code (csharp):
    1.  
    2. //Do this computation only once or just set it to whatever value you want
    3. //by making this a public variable and setting it in the inspector
    4. float maxVelocityMagnitude = maxVelocity.magnitude;
    5.  
    6. if(projectedVelocity.magnitude > maxVelocityMagnitude && rigidBody.velocity.magnitude <  maxVelocityMagnitude)
    7. {
    8.     difference = projectedVelocity - maxVelocity;
    9. }
    10.  
    Case 1 should be covered then just like before, but now it will only set the difference to a non-zero value if the rigidBody was going slower than the maxVelocityMagnitude. Otherwise difference stays at 0 and it doesn't change the velocity in order to satisfy case 2. I'd think then you could probably forget about all the complicated ifs and worrying about the signs of the numbers.
     
    Last edited: Jul 2, 2015
  8. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    What it looks like you're trying to do is let something speed up, but not overshoot the max velocity. At the same time, if for some reason the object is moving faster than the max velocity, do nothing.

    My thought process on this was breaking it into two parts in that if statement. First part:

    projectedVelocity.magnitude > maxVelocityMagnitude

    At this point you've computed how fast the object will be moving if you added the full addVelocity. You'll only compute a difference if the new velocity would be less than the maxVelocityMagnitude. This is a good way of doing things because the directions don't matter then, so you can forget about the signs of the components and it should work in any number of dimensions.

    So to modify the velocity (getting a non-zero difference), the above would have to be true and the following would have to be true too:

    rigidBody.velocity.magnitude < maxVelocityMagnitude

    If the body was moving faster than maxVelocityMagnitude before you did anything to it with addedVelocity, difference would stay at 0 and the velocity would just change by whatever your addingVelocity variable was. Is that good enough? Another way to write it would be this:

    Code (csharp):
    1.  
    2. Vector3 difference = Vector3.zero;  //If either of the next if statements is not true, difference magnitude will be 0.
    3.  
    4. if(rigidBody.velocity.magnitude <  maxVelocityMagnitude)
    5. {
    6.     if(projectedVelocity.magnitude > maxVelocityMagnitude )
    7.     {
    8.        difference = projectedVelocity - maxVelocity;
    9.     }
    10. }
    11.  
     
    Last edited: Jul 2, 2015
  9. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    If my math is correct, this still does not give the desired results.

    - Example 1-
    maxVelocity = 4,0,0
    addingVelocity = 2,0,0
    myRigidbody.velocity = 3,0,0

    goal velocity to add = 1,0,0

    Code (CSharp):
    1. if(3 < 4) //it is
    2. {
    3.     if(5 > 4) //it is
    4.     {
    5.         difference = 1,0,0; //5,0,0 - 4,0,0
    6.     }
    7. }
    Goal velocity of 1,0,0 is reached

    - Example 2-
    maxVelocity = 4,0,0
    addingVelocity = 2,0,0
    myRigidbody.velocity = 5,0,0

    goal velocity to add = 0,0,0

    Code (CSharp):
    1. if(5 < 4) //it is not
    2. {
    3.     //skip
    4. }
    Goal velocity of 0,0,0 is reached

    - Example 3-
    maxVelocity = -4,0,0
    addingVelocity = -2,0,0
    myRigidbody.velocity = 5,0,0

    goal velocity to add = -2,0,0

    Code (CSharp):
    1. if(5 < 4) //it is not
    2. {
    3.     //skip
    4. }
    Goal velocity of -2,0,0 is not reached

    It seems the signs of the vectors are whats giving you problems as well ;)

    Please also keep in mind that the signs of each vector value x y and z may have different signs as well, so I do not think comparing them with magnitude will be the way to go, we need to do it per value.

    If you did not see my example of what I did so far in my previous post, check it out. I think I already have the correct method for when all signs are the same, but when they are not, that is my issue.
     
  10. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Is it only ever going to affect the x axis? Solution is alot simpler if it never moves on y and z
    if no, question 2: how are you creating a max velocity in 3 dimensions?
    [maxVelocity = 2,3,4] suggests that it can go as fast as it wants in the negative directions
     
  11. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    Example 3: I though that's what you wanted.

    Is it "goal velocity to add" or is it "goal velocity?" In that last case myRigidbody.velocity.magnitude is 5 while maxVelocity.magnitude is 4. Since myRigidbody is going faster than your maxVelocity.magnitude I thought you didn't want it to be modified then except by your addingVelocity variable which would cap the velocity if it was accelerating beyond it, but leave it alone if you it wasn't. The if block gets skipped and difference = 0, so you're left with changing velocity by your original addingVelocity. If that's not what you want you'll have to be more specific.

    Here's a walkthrough:
    Code (csharp):
    1.  
    2. //Given:
    3. Vector3 maxVelocity = -4...;
    4. Vector3 addingVelocity =-2 ...;
    5. myRigidbody.velocity = 5....;
    6.  
    7. //New variables:
    8. Vector3 projectedVelocity = myRigidbody.velocity + addingVelocity;
    9.  
    At this point:
    projectedVelocity = 3.
    rigidBody.velocity.magnitude = 5
    maxVelocityMagnitude = 4

    Now the first if():
    Code (csharp):
    1.  
    2. if(rigidBody.velocity.magnitude <  maxVelocityMagnitude)
    3.  
    if(5<4)

    At this point difference = 0 so:
    Code (csharp):
    1.  
    2. goalVelocityToAdd = addingVelocity - difference;
    3.  
    goalVelocityToAdd = -2 - 0
    goalVelocityToAdd = -2

    Your original goalVelocityToAdd is left untouched. You're now free to change the velocity (slow down perhaps or accelerate in a direction that does not increase velocity beyond maxVelocityMagnitude?) without it being modified. If that's not what you wanted then you'll have to explain it again because I then don't understand what you're trying to do. I thought you were just trying to restrict/modify the velocity to hit a certain magnitude on acceleration unless it was already moving faster than that.
     
  12. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    Good point, I just realized that now. Yeah, I don't understand what he's trying to do here then.
     
  13. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    Are you trying to limit the velocity separately in different directions? I.e., only allow velocity = 2 in x direction with velocity = 3 in y and so forth?
     
  14. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    If so, you ought to be able to follow the same basic pattern and thinking I laid out, probably. Just do it separately on each axis and where you see magnitude, use absolute value instead.
     
  15. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    It can be any direction (any axis, multiple axis)

    Goal velocity to add or goal velocity is basically the same. Even if my current rigidbody velocity is 5,0,0 and I am trying to add a velocity of -3, dont look at it as subtracting velocity, but instead as just adding velocity in the other direction as long as my maxVelocity is also in that direction.
    (In other words, when your player moves left and right, even though it might be going from +x to -x, you don't see it as going to a negative direction, its just moving towards the left side, or adding its movement to the left.)

    I'll try to explain in more detail.

    The max velocity I want to reach is a magnitude of 4 in what every velocity I plug in.
    Lets say I want to add a velocity of 2,0,0
    My rigidbodies current velocity is 3,0,0
    The max I want to add to my rigidbody velocity in the x axis is 4, but I am trying to add 2 and the current velocity is already 3, so I cannot add the 2 or it will go over the max of 4, so I need to calculate what I can add.

    Now the confusing part is lets say
    The max velocity I want to reach is a magnitude of 4 in what every velocity I plug in.
    Lets say I want to add a velocity of -2,0,0
    My rigidbodies current velocity is 5,0,0
    The max I want to add to my rigidbody velocity in the x axis is -4 and I am trying to add -2, but the current velocity is 5. Since the target max velocity is in the negative x, I need to find out how much I can add to move towards my target max velocity. Since the velocity is 5 and I want to add -2, 5 + -2 is 3, which is not past the max velocity of -4, so I am allowed to move -2.

    If the max velocity I want to reach is a magnitude of 1 in what every velocity I plug in.
    Lets say I want to add a velocity of -2,0,0
    My rigidbodies current velocity is 0,0,0
    The max velocity I can have is -1,0,0 , but I am trying to add -2 to the current 0 velocity, therefore I need to find out how much I could add to not go past the -1, which would be -1.

    Hopefully this makes things more clear. The key point here is I need to find out how much I can add to move towards my target max velocity.
    I will edit my main post with this line.

    Please check one of my previous posts where I posted some code I did to try and solve this. This is exactly what I am doing for when all the signs are the same, but when they are not, this method will not work (as far as I can tell).
     
  16. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    hpjohn, I think what he probably wants is for maxVelocity.x = 2 probably to mean -2 and 2. So for instance in his example 3:


    maxVelocity = -4,0,0
    addingVelocity = -2,0,0
    myRigidbody.velocity = 5,0,0
    goal velocity to add = -2,0,0


    his velocity on the next step will become:
    myRigidbody.velocity.x = myRigidbody.velocity.x + goal velocity to add.x
    myRigidbody.velocity.x = 5 - 2
    myRigidbody.velocity.x = 3

    So it was moving to the right really fast for whatever reason (above the max velocity of 4 or -4), but the player can still accelerate left in order to slow down without having the speed capped in the meantime down from 5 to 4.

    If so, he ought to be able to do pretty much the same thing I laid out, but using absolute values instead of magnitudes and doing it separately for each axis. Too late for me to try it now, but if he hasn't figured it out by tomorrow I'll come back.
     
  17. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    Is this what you mean? This is from my example code that I posted in a previous post above.
    Code (CSharp):
    1.         float[] limitedVelocityValues = new float[3];
    2.  
    3.         for(int i = 0; i < limitedVelocityValues.Length; i++)
    4.         {
    5.             if(Mathf.Sign(velocity.SelectAxis(i)) == Mathf.Sign(myRigidbody.velocity.SelectAxis(i)))
    6.             {
    7.                 if(Mathf.Abs(velocity.SelectAxis(i)) + Mathf.Abs(myRigidbody.velocity.SelectAxis(i)) < Mathf.Abs(maxVelocity.SelectAxis(i)))
    8.                 {
    9.                     limitedVelocityValues[i] = velocity.SelectAxis(i);
    10.                 }else{
    11.                     float x = Mathf.Abs(maxVelocity.SelectAxis(i)) - Mathf.Abs(myRigidbody.velocity.SelectAxis(i));
    12.                     limitedVelocityValues[i] = (x > 0) ? x : 0;
    13.                 }
    14.             }

    If so, then I do not think this works for when the signs are not equal.

    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.
     
  18. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    No, I meant rewrite my code to do it on each axis separately. That if/elseif stuff is too nasty for me to even look at. ;)
     
  19. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    So to clarify more, you want to have a maxVelocityMagnitude, rather than a specific maxVelocity - (2.5,2.5,2.5) exceeds a magnitude of 4, but none of the components do.
    And let's say you are travelling in 4,0,0 and wish to add 0,1,0 then things get complicated
     
  20. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    In my example code, the maxVelocity is determined like this
    Vector3 maxVelocity = velocity.normalized * maxMagnitude;
    (Check my edit below on the issue of how I am getting the maxVelocity.)
    As long as each resulting velocity value (x,y,z) does not go past that target maxVelocity, then it is valid.

    Example -
    maxMagnitude = 4;
    velocity = 1,0,1
    maxVelocity = 4,0,4
    The most the velocity could end up being is 3,0,3 but this depends on what the current rigidbody velocity is.

    EDIT - However, I just realized that normalizing doesnt put the values to 1, but the concept is the same. I do not want the velocity to go over what ever the maxVelocity is. It should not matter how I determine the maxVelocity.

    What do you mean by traveling in 4,0,0.
    Do you mean my rigidbodies velocity is currently moving in 4,0,0 and I am trying to add a 0,1,0 to it? In that case, the maxVelocity would be 0,4,0 (if the magnitude is 4) and the velocity would have to be somewhere from 0 + since the maxVelocity is a positive (velocity and max velocity will always be the same sign).
    If I was adding 0,1,0 and the max allowed was 0,4,0 and the current velocity is 4,0,0 then I can just go ahead and add the 0,1,0 since it does not go over the 0,4,0
     
    Last edited: Jul 2, 2015
  21. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Except now you have velocity of 4,1,0 which has a magnitude of 4.12, exceeding your max
     
  22. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    No, the maxVelocity is more so the maxVelocityToAdd, not the overall max velocity.
    I will edit my main post as this can be a big misunderstanding.

    To clarify, we do not care what the end result rigidbody.velocity magnitude is, all we care is that given our addingVelocity and the maxVelocity we can add, I do not want to OverAdd to the rigidbody velocity. I only want to add what is required to reach the target maxVelocityToAdd
     
  23. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,294
    rigidbody.AddVelocity(someVelocity);
    rigidbody.velocity = Vector3.ClampMagnitude(rigidbody.velocity, maxSpeed);


    That's the only way to get exact results - otherwise drag and the Gods Of PhysX Randomness will cause the velocity to fluctuate.
     
  24. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    That is clamping the whole rigidbody velocity, which is not the result I want.
    In other words, if something pushed my player adding great force to make him slide, but he starts to walk, your method above will make him instantly stop, no?

    I just want to make sure that if I am adding a velocity of 2 in what every axis (lets say x) and the maxVelocity I am allowed to add (max speed of the player) is 4 in that same axis, and the current rigidbody velocity is 3 in that same axis, then I can only add 1 more velocity.
    However, if the velocity I am trying to add is in the other direction, such as -2 in the x, and the max I can add is -4 in the x, and the rigidbodies current velocity is 5 in the x, I am allowed to just add -2 because the ending result is not making my rigidbody velocity go past -4 in the x. If the velocity was already past -4 in the x then I cannot add anymore.
     
  25. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Is this to prevent bunny hop acceleration?
    The player control can only apply acceleration in a specific direction if he is not already moving faster than some max in that direction? But if you are moving in a direction fast than your feet can push you (due to being pushed by explosion for example) then trying to move in that direction won't slow you down
     
  26. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    Im not doing this for anything bunny hop related, but yes, as I stated in my original post
    "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."
    I guess the confusing part was not specifying about going in the negative direction.

    So you mean like this? If so, then it still does not work.
    Your code
    Code (CSharp):
    1. Vector3 projectedVelocity = myRigidbody.velocity + addingVelocity;
    2. Vector3 difference = Vector3.zero;
    3.  
    4. if(rigidBody.velocity.magnitude <  maxVelocityMagnitude)
    5. {
    6.     if(projectedVelocity.magnitude > maxVelocityMagnitude )
    7.     {
    8.        difference = projectedVelocity - maxVelocity;
    9.     }
    10. }

    Converted to
    Code (CSharp):
    1. maxVelocityAbsX = Mathf.Abs(maxVelocity.x);
    2. VelocityAbsX = Mathf.Abs(velocity.x);
    3. rigidbodyVelocityAbsX = Mathf.Abs(rigidbody.velocity.x);
    4.  
    5. projectedVelocityAbsX = rigidbodyVelocityAbsX - VelocityAbsX;
    6. or
    7. projectedVelocityX = rigidbody.velocity.x - velocity.x;
    8.  
    9. differenceX = 0;
    10.  
    11. if(rigidBody.velocity.magnitude < maxVelocityAbsX)
    12. {
    13.     if(projectedVelocityAbsX > maxVelocityAbsX )
    14.     {
    15.         differenceX = projectedVelocityAbsX - maxVelocityAbsX;
    16.         or
    17.         differenceX = projectedVelocityX - maxVelocityX;
    18.     }
    19. }

    - Example 3-
    maxVelocity = -4,0,0
    addingVelocity = -2,0,0
    myRigidbody.velocity = 5,0,0

    goal velocity to add = -2,0,0 (Note - we do not know the goal velocity, this is what we are trying to find)

    Code (CSharp):
    1. maxVelocityAbsX = 4;//Mathf.Abs(-4)
    2. VelocityAbsX = 2;//Mathf.Abs(-2)
    3. rigidbodyVelocityAbsX = 5;//Mathf.Abs(5)
    4.  
    5. projectedVelocityAbsX = 1;//5 - 4
    6. or
    7. projectedVelocityX = 9;//5 - -4
    8.  
    9. differenceX = 0;
    10.  
    11. if(5 < 4) //it is not
    12. {
    13.     //skip
    14. }
    differenceX is 0, it should have been -2; This is wrong.

    The ultimate goal of all this is...
    I want it to be instant when the player presses to walk, no slow charge up to walk. However, they can only walk a certain max speed.
    If they get hit by some force that pushes them back, and they start walking against that force, they will be sliding back but slowly stoping as they keep adding more and more force in said direction.
    I need the amount of force that they push against the other force to be no greater than the original velocity given.
    So if they were walking of a velocity of 2,0,0 and the max they can give is 4,0,0, the end resulting velocity cannot be below 0 or above 2, and if the rigidbody velocity is already at 4,0,0, then the added velocity is just 0. If the rigidbody velocity is 5,0,0, I do not want the added velocity to be -1,0,0
    If velocity is -2,0,0 and the max is -4,0,0, and the rigidbody velocity is 3,0,0 then the velocity added can be -2,0,0 since 3 + -2 is not past -4
     
    Last edited: Jul 2, 2015
  27. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    These quantities have three components and a magnitude. For example, your "velocity to add" is essentially just "acceleration" in the context of this discussion. This means you have 4 variables you can work with:

    acceleration.x
    acceleration.y
    acceleration.z
    acceleration.magnitude

    You also have velocity which is another 4 variables you can be using:
    velocity.x
    velocity.y
    velocity.z
    velocity.magnitude


    All you're trying to do is limit these values by modifying the acceleration so it doesn't go beyond the max velocity. hpjohn and I are trying to figure out which values you're trying to limit. Are you trying to limit the x/y/z components directly or are you trying to limit the magnitudes? These are very different things. It can be done either way but I need to know which way you want it. What I wrote for you was a way to limit all this via the magnitudes, but now it seems that's not really what you want.

    It sounds to me like you've probably got a game character or vehicle or something that you want to accelerate no more than so quickly while at the same time not exceeding a maximum velocity.magnitude (speed). What I handed you should do that, it does indeed return in all 3 cases the values you specified in your original post. This brings us to maxVelocity. Again there are 4 variables here that we could be working with:

    maxVelocity.x
    maxVelocity.y
    maxVelocity.z
    maxVelocity.magnitude

    Do you want to set the x/y/z components directly so the max velocities are different along different axes, or do you really just care about the magnitude (the max speed in any direction)? If so, you don't really need the components, only the magnitude.

    Same for acceleration:
    maxAcceleration.x
    maxAcceleration.y
    maxAcceleration.z
    maxAcceleration.magnitude


    I assumed you wanted to limit maxVelocity.magnitude and maxAcceleration.magnitude which means limiting the speed and acceleration in any directions to some value. We would do this by computing your goalVelocityToAdd (I would call this targetAcceleration) which then modifies the acceleration so you don't go over the maxVelocity.magnitude, while at the same time not exceeding the maxAcceleration.magnitude.

    hpjohn asked you about the three components of maxVelocity (which I missed until he pointed that out), so I think we're both wondering whether you want to limit the velocity (and acceleration for that matter) in the x direction to one speed, the velocity in the y direction to another speed, and the velocity in the z direction to another speed all separately, of if you just want it to work the same in all directions in 3D.

    So here are my questions before I spend any more time on this:

    1) Do you want to limit the acceleration.magnitude, or do you want to set values for maxAcceleration.x and .y and .z separately?

    2) Do you want to limit the velocity.magnitude, or do you want to set values for maxVelocity.x and .y and .z separately? I.e., maybe you want to allow your character/vehicle/whatever to move in the x direction at a different speed than in the y or z directions.

    It's important to clarify this before we proceed. It's not entirely clear from your posts what you really want to do there. I gave you probably the most common case but it's not what you wanted, so I have to ask for clarification here. If you can answer the two questions I can probably help. I spent 14 years writing physics engines and am at least vaguely familiar with limiting and modifying accelerations and velocities to hit specific targets in various directions for all kinds of goofy reasons. :p

    If you can't answer the questions for sure, maybe you can explain what the game does and how you want things to move. Then I can help you decide on whether it should be limiting components or limiting magnitudes. I'm happy to help, we can do it either way, but I need to know which way you want things to work. Perhaps while I was writing this you answered the question already. If so, I'll come back "tomorrow" and give this thread another read. It's almost 6am here and I really should go to bed. :D
     
    Last edited: Jul 2, 2015
  28. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    Let me ask the question another way:

    Do you want to limit the acceleration to 1g (or whatever number) in any direction? Do you want the maximum speed to be 20 m/s (or whatever number) in any direction? Or do you want it to be able to go 10 m/s in the x direction, 20 m/s in the y direction, and 30 m/s in the z direction?

    I.e., Which do you care about? The components or the magnitudes?
     
  29. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Whats the 'correct' result going to be in this scenario? Don't worry about the maths for it, just what you want it to be
    (limit to 2 dimensions for now)

    maxVelocity = 1.8, 3.6
    addingVelocity = 1,2
    myRigidbody.velocity = 4,3

    goal velocity to add = ?
    resulting rb.velocity = 4,3 + ?
    If you can give a satisfactory solution to this, i can give you the maths
    (nb. we are probably talking dot products here)
     
  30. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    result velocity to add = 0, .6 <- this is the result we are trying to get from your math
    result rigidbody velocity = 4, 3.6

    The rigidbody velocity x is already way past the allowed velocity, so we dont add anything, but the y still has room for .6, and we are trying to add 2 so we have the .6 to give. If we were adding 1, .3, then we can only add .3


    I have probably said confusing/wrong/contradicting things in my past posts, so hopefully this clears things up.
     
    Last edited: Jul 2, 2015
  31. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    When you say goalVelocityToAdd, do you mean what I have been calling the maxVelocity, or are you talking about the "goal velocity to add =..." That I have been putting in my examples? If it is the later, than please understand that the goal velocity to add is what we are trying to get. I do not know the goal velocity to add. That is the goal...

    I care about the magnitude.
    (EDIT - when I said I cared about the magnitude, I was thinking more so that I want each vector component to not go past the maxVelocity we determined by the magnitude, so in a way I do care about the magnitude, however, I want to work on each component separately and not just focus on the magnitude when doing the calculations.)

    If my maxMagnitude is 4...
    The velocity I am trying to add is 2,0,0
    The maxVelocity I am allowed to have is 4,0,0 in the rigidbodies velocity

    If my maxMagnitude is 4...
    The velocity I am trying to add is 1,0,1
    The maxVelocity I am allowed to have is something like 2.8,0,2.8 in the rigidbodies velocity

    If the rigidbody velocity is 3,0,2.7 then I still have room to add .1 to the 2.7, but I cannot add anymore to the 3. So if I am trying to add 1,0,1 then the velocity I would end up adding can only be 0,0,.1
    If I am trying to add a velocity of 1,0,.05 then I can only add that ,.05 and if I am trying to add a velocity of 1,0,0 then I can add nothing

    However, if I am trying to add -1,0,0, then my maxVelocity would move to the negative side, and if my rigidbody is 5,0,0 and I am trying to add -1,0,0 and I can add a max of -4,0,0, then I can go ahead and add the -1,0,0 since the rigidbody velocity will not go past the -4


    Think of all this as me trying to move towards my maxVelocity, but not have the rigidbody go past it. If the rigidbody went past it, then we just dont add to it and either wait till we go the other direction to push against it, or let gravity/friction handle it.
     
    Last edited: Jul 2, 2015
  32. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    Right, I understand. That's why my code computed it at the end.

    Are you sure my example doesn't do exactly what you wanted it to do? I'm pretty sure case 3 returned the correct goalVelocityToAdd along with the other cases.
     
  33. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    My goalVelocityToAdd is your "goal velocity to add." My maxVelocity is your maxVelocity.
     
  34. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    Please post the code again just to make it official, just in case.
     
  35. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    See posts 4 and 7.
     
  36. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    Or 4 and 8. Take your pick.
     
  37. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    Want to know the really easy way to do all this? Just use forces and let PhysX do its job. Limit the force magnitude (which limits your acceleration) and limit the velocities with that clamp function and you shouldn't have to mess with any of this stuff ever again. ;)
     
  38. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    It seems it does work for example #3, but I never saw that because when I tested it, it worked for example 1, but failed for example 2, so I just stopped checking.

    Maybe I can mix things around. I will do more testing.
     
  39. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    I made post 7 and 8 after it failed with example 2. That's when you said example 3 didn't work...

    Anyway, I think I'm done with this one. Maybe john can take it from here. Good luck.
     
  40. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    You really want to work piece-wise in components? this is so wrong, theres no real-world equivalent to this at all
    You might get the numbers you want, but the behavior will seem really weird

    Code (CSharp):
    1.         float maxMagnitude = 4;
    2.         Vector3 addVelocity = new Vector3( 1, 0, 2 ); //or whatever from input
    3.         Vector3 maxVelocity = addVelocity.normalized * maxMagnitude;
    4.         Vector3 currentVelocity = GetComponent<Rigidbody>().velocity;
    5.  
    6.         Vector3 goalVelocity = Vector3.zero;
    7.  
    8.         for ( int i = 0; i < 3; i++ ) {
    9.             if ( Mathf.Sign( maxVelocity[i] ) != Mathf.Sign( currentVelocity[i] ) ) {
    10.                 goalVelocity[i] = Mathf.Min( Mathf.Abs( addVelocity[i] ), Mathf.Abs( maxVelocity[i] ) ) * Mathf.Sign( addVelocity[i] );
    11.             } else if ( Mathf.Abs( currentVelocity[i] ) < Mathf.Abs( maxVelocity[i] ) ) {
    12.                 goalVelocity[i] = Mathf.Min( Mathf.Abs( addVelocity[i] ), Mathf.Abs( maxVelocity[i] - currentVelocity[i] ) ) * Mathf.Sign( addVelocity[i] );
    13.             }
    14.         }
     
  41. Todd-Wasson

    Todd-Wasson

    Joined:
    Aug 7, 2014
    Posts:
    1,079
    Ok.

    Yes, that's limiting the magnitude.


    And this one is limiting the individual component.

    You want it both ways at the same time. This is just a really weird thing to do and it's going to act funny, probably not really what you want. Depending on your max settings, you could get an object that moves (and maybe accelerates) slower at 45 degree angles than it does along an axis. It'll be goofy.

    I suggest you just stick to the magnitudes and forget about limiting any one particular component to a maximum of 3 or whatever unless the motion is purely in that direction. If it is in the direction, the magnitude limits will take care of it. This approach will make some physical sense and feel natural.

    Forget about components and restricting them one by one. Just think about restricting magnitudes. An object can accelerate at some rate in any direction, whether it's along the x or y or z or any combination of them. Same goes for speeds. You can go 100 km/h up, down, left, right, northwest or any other direction, period.

    Think "total acceleration in any direction" and "speed regardless of direction." All the signs you're talking about will just disappear like it does in my code, they are just directions after all, and you end up with only a couple of if() statements at the most.
     
  42. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    This might work, need to do more tests though.

    I don't see why this is all so wrong to do?
    Is this not similar to AddForce ForceMode.Force except addforce will keep adding, and now here we are able to prevent it from constantly adding?
    If an object pushed me to move in -x and I start walking in -x as well, is it so wrong for me to not want to add to the speed and just let it be? However, if I am walking in -x as well as z, then I want to add to the z while not adding to the x.

    I really dont see what is so wrong with this.

    Edit - But all aside, thank you both for spending a lot of time with me here. I really appreciate it! =)

    Edit2 - There might be a bug with the code, or it might also be something on my part. Ill have to check more.

    P.S - I had no idea you could do vector[index] to get the individual float values. I was using a helper method .SelectAxis(int), but now I don't need to =). That alone was worth this thread.
     
    Last edited: Jul 2, 2015
  43. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    I think this method works, but more testing will tell.

    Code (CSharp):
    1.     public static void LimitAddRelativeForce(this Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis, ForceMode forceMode)
    2.     {
    3.         myRigidbody.AddRelativeForce(LimitLocalVelocity(myRigidbody, velocity, maxMagnitude, clampAxis), forceMode);
    4.     }
    5.  
    6.     public static void LimitHorizontalAddRelativeForce(this Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, ForceMode forceMode)
    7.     {
    8.         LimitAddRelativeForce(myRigidbody, velocity, maxMagnitude, new Vector3(1, 0, 1), forceMode);
    9.     }
    Code (CSharp):
    1.     public static Vector3 LimitVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis)
    2.     {
    3.         Vector3 clampedVelocity = ClampVelocity(myRigidbody, velocity, maxMagnitude, clampAxis);
    4.         return LimitVelocity(myRigidbody, velocity, clampedVelocity, maxMagnitude);
    5.     }
    6.     public static Vector3 LimitLocalVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis)
    7.     {
    8.         Vector3 clampedVelocity = ClampLocalVelocity(myRigidbody, velocity, maxMagnitude, clampAxis);
    9.         return LimitVelocity(myRigidbody, velocity, clampedVelocity, maxMagnitude);
    10.     }
    11.     static Vector3 LimitVelocity(Rigidbody myRigidbody, Vector3 velocity, Vector3 clampedVelocity, float maxMagnitude)
    12.     {
    13.         for(int i = 0; i < 3; i++)
    14.         {
    15.             if(Mathf.Sign(clampedVelocity[i]) == Mathf.Sign(velocity[i]))
    16.             {
    17.                 clampedVelocity[i] = Mathf.Sign(clampedVelocity[i]) * (Mathf.Clamp(Mathf.Abs(clampedVelocity[i]), 0, Mathf.Abs(velocity[i])));
    18.             }else{
    19.                 clampedVelocity[i] = 0;
    20.             }
    21.         }
    22.         return clampedVelocity;
    23.     }
    Code (CSharp):
    1.     public static Vector3 ClampVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis)
    2.     {
    3.         return Vector3.ClampMagnitude(velocity - myRigidbody.velocity, maxMagnitude).SelectAxis(clampAxis);
    4.     }
    5.  
    6.     public static Vector3 ClampLocalVelocity(Rigidbody myRigidbody, Vector3 velocity, float maxMagnitude, Vector3 clampAxis)
    7.     {
    8.         Vector3 clampedVelocity = ClampVelocity(myRigidbody, myRigidbody.transform.TransformDirection(velocity), maxMagnitude, Vector3.one);
    9.         return myRigidbody.transform.InverseTransformDirection(clampedVelocity).SelectAxis(clampAxis);
    10.     }
    Code (CSharp):
    1.     public static Vector3 SelectAxis(this Vector3 vector, Vector3 axis)
    2.     {
    3.         Vector3 selectedAxis = Vector3.zero;
    4.         if(axis.x != 0) selectedAxis.x = vector.x;
    5.         if(axis.y != 0) selectedAxis.y = vector.y;
    6.         if(axis.z != 0) selectedAxis.z = vector.z;
    7.  
    8.         return selectedAxis;
    9.     }

    The usage looks like this...
    Code (CSharp):
    1. Vector3 targetVelocity = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized * force;
    2. myRigidbody.LimitHorizontalAddRelativeForce(targetVelocity, force, ForceMode.VelocityChange);
    edit - One big problem this has is it causes you to move faster when going against walls that have no friction.
     
    Last edited: Jul 5, 2015
  44. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    In your 8th post, you left out part of the code that I ultimately forgot to put in when testing. The important part left out was
    "Vector3 goalVelocityToAdd = addingVelocity - difference;"
    This made #3 fail when I was testing.

    When I asked you to post the code again just to make sure, this was the reason why. You were putting code all over the place and I wanted to make sure I had everything together, but instead you replied with just post numbers (which, by the way, when you said 4th post, I went counting down as 0,1,2,3 and then saw your post. Made me confused for a second XD)

    Your code..
    Code (CSharp):
    1.         Vector3 maxVelocity = velocity.normalized * maxMagnitude;
    2.         Vector3 projectedVelocity = myRigidbody.velocity + velocity;
    3.         Vector3 difference = Vector3.zero;
    4.  
    5.         if(myRigidbody.velocity.magnitude < maxVelocity.magnitude)
    6.         {
    7.             if(projectedVelocity.magnitude > maxVelocity.magnitude )
    8.             {
    9.                difference = projectedVelocity - maxVelocity;
    10.             }
    11.         }
    12.         return velocity - difference;

    doesnt seem to work out of the box (doesnt give the results Im looking for when put into use). I think I need to do something somewhere like this line of code in my possible solution I posted above "Mathf.Sign(clampedVelocity) * (Mathf.Clamp(Mathf.Abs(clampedVelocity), 0, Mathf.Abs(velocity)));"
    Its probably got to do with dealing with each component of the vector separately, which your code doesnt do.

    All in all I think I have what I need, but time will tell. Thank you all so much for the help!
     
    Last edited: Jul 5, 2015