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

Slippery Movement

Discussion in 'Scripting' started by UniversalGesture, Mar 5, 2021.

  1. UniversalGesture

    UniversalGesture

    Joined:
    May 29, 2017
    Posts:
    125
    So far I've been using

    GetComponent<Rigidbody>().AddForce(transform.forward * 100);

    to move my character when I press the up key but the movement is really slippery and has too much inertia in the previous direction when I change course.

    Increasing the drag doesn't really fix this. I know I could just set the position but this may cause my character to clip through objects.

    How can I fix this? (This is for 3D movement)
     
  2. bobisgod234

    bobisgod234

    Joined:
    Nov 15, 2016
    Posts:
    1,042
    A lot of games like to add extra force when you are trying to move in the opposite direction than you are currently travelling. Try doing something like that.
     
  3. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,723
    Acceleration = Force / Mass.

    If you want to accelerate faster, you must increase the force, or decrease the mass of the object. (Acceleration just means change in velocity, so it includes deceleration as well).
     
    Joe-Censored and SparrowGS like this.
  4. UniversalGesture

    UniversalGesture

    Joined:
    May 29, 2017
    Posts:
    125
    That's not the issue.
     
  5. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,723
    It is the issue. To slow down your object you must apply a force in the opposite direction of motion.
     
    SparrowGS likes this.
  6. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,723
    upload_2021-3-4_22-41-29.png
    Let's say you are currently travelling in the direction indicated by the dark blue arrow. You want to change direction to be travelling in the direction indicated by the light blue arrow.

    In order to do this, you need to add a force in the direction of the red arrow. To further break the red arrow down, there is the component indicated by the pink arrow in the direction you want to be going. There is also the component indicated by the small green arrow which you need to counteract your existing velocity in the direction of the dark blue arrow.

    Without that green component, you will continue sliding in the direction of the dark blue arrow due to inertia, as you described, and will end up going up and to the right. So the answer is to apply a force in the direction of the green arrow, as well as the pink arrow you are probably using currently.
     
  7. UniversalGesture

    UniversalGesture

    Joined:
    May 29, 2017
    Posts:
    125
    Thanks for the info! Greatly appreciated.
     
  8. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,923
    Increasing the drag enough will fix it, but you may need to increase the force added to make up for the extra drag. Or you could add code-drag only when the button is held. That way it will coast normally when you let go:
    Code (CSharp):
    1. if(acellButtonPressed) {
    2.   myRB.velocity*=0.6f; // massive drag if over several frames
    3.   // does the same thing as AddForce:
    4.   myRB.velocity+=transform.forward*100*Time.deltaTime;
    5. }
     
    UniversalGesture likes this.
  9. UniversalGesture

    UniversalGesture

    Joined:
    May 29, 2017
    Posts:
    125
    I like the idea of adding a counter force, but now the question becomes how do I obtain what the initial direction was after I rotate my camera say 2 degrees?
     
  10. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,723
    Rigidbody velocity is Rigidbody velocity. you'll basically just want to apply a force counter to whichever component of the current velocity is not in the direction you are trying to go
     
  11. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    1,923
    Using local coordinates is like taking a hammer to the problem, but it will work to isolate the "way I'm going" part of the old vector from the rest. The idea is you figure out which way you want to move and call that your local space -- that direction counts as your +z. Then convert your current velocity into it. Now +z is good, and x and y are going the wrong way and should be reduced. Then convert the result back to global. Ex (80% of this is standard "to local, adjust, back to global". It's also from memory):
    Code (CSharp):
    1. Quaternion wantDirection=transform,forward; // assuming accel is only in facing direction
    2. Vector3 curVelLocal=Quaternion.Inverse(wantDirection)*myRB.velocity;
    3.  
    4. // crush the x and y in some way:
    5. curVelLocal.x=Mathf.MoveTowards(curVelLocal.x,0,1.0f*Time.deltaTime);
    6. curVelLocal.y=Mathf.MoveTowards(curVelLocal.y,0,1.0f*Time.deltaTime);
    7.  
    8. // convert back to global:
    9. Vector3 oldVelAdjusted=wantDirection*curVelLocal;
    10. // add to it, or just put it back (so we can use AddForce):
    11. myRB.velocity=oldVelAdjusted;
    The overall effect is like drag only for "sideways", none for forward. I used MoveTowards for fun.
     
    PraetorBlue likes this.
  12. UniversalGesture

    UniversalGesture

    Joined:
    May 29, 2017
    Posts:
    125
    Thank you everyone! Overall I got it figured out (thanks to your help)
     
  13. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,768