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

Resolved My character is moving but not so smoothly

Discussion in 'Scripting' started by seanyeet6, Jan 17, 2021.

  1. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    my player is moving a fixed position which is what I want however it teleports there

    Code (CSharp):
    1.         if (Input.GetKeyDown("d"))
    2.         {
    3.             transform.Translate(new Vector3(1, 0, 0));
    4.         }
    5.        
    6.         if (Input.GetKeyDown("a"))
    7.         {
    8.             transform.Translate(new Vector3(-1, 0, 0));
    9.         }
    10.  
    11.         if (Input.GetKeyDown("w"))
    12.         {
    13.             transform.Translate(new Vector3(0, 0, 1));
    14.         }
    a little help
     
  2. djlevana18

    djlevana18

    Joined:
    Dec 11, 2020
    Posts:
    25
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. [System.Serializable]
    5. public enum SIDE {Left, Mid, Right}
    6.  
    7.  
    8. public class playermove : MonoBehaviour
    9. {
    10.     public SIDE m_side = SIDE.Mid;
    11.     float NewXpos = 0f;
    12.     [HideInInspector]
    13.     public bool SwipeLeft, SwipeRight;
    14.     public bool Swipeup, Swipedown;
    15.     public float JumpPower = 7f;
    16.     private float y;
    17.     public float XValue;
    18.     public bool Injump;
    19.     public bool InRoll;
    20.     private CharacterController m_char;
    21.     private float x;
    22.     public float speeddodge;
    23.     private float ColHight;
    24.     private float ColCenterY;
    25.     float FwdSpeed = 30f;
    26.    
    27.  
    28.     void Start()
    29.     {
    30.         m_char = GetComponent<CharacterController>();
    31.         ColHight = m_char.height;
    32.         ColCenterY = m_char.center.y;
    33.         transform.position = Vector3.zero;
    34.     }
    35.     void Update()
    36.     {
    37.         SwipeLeft = Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow);
    38.        
    39.         SwipeRight = Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow);
    40.         Swipeup = Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.UpArrow);
    41.         Swipedown = Input.GetKeyDown(KeyCode.S) || Input.GetKeyDown(KeyCode.DownArrow);
    42.         if (SwipeLeft)
    43.         {
    44.             if(m_side == SIDE.Mid)
    45.             {
    46.                 NewXpos = -XValue;
    47.                 m_side = SIDE.Left;
    48.             }else if(m_side == SIDE.Right)
    49.             {
    50.                 NewXpos = 0;
    51.                 m_side = SIDE.Mid;
    52.             }
    53.         }
    54.         else if (SwipeLeft)
    55.         {
    56.             if (m_side == SIDE.Left)
    57.             {
    58.                 NewXpos = -XValue + -2;
    59.                 m_side = SIDE.M_Left;
    60.             }
    61.             else if (m_side == SIDE.Left)
    62.             {
    63.                 NewXpos = -XValue;
    64.                 m_side = SIDE.Left;
    65.             }
    66.         }
    67.         else if (SwipeRight)
    68.         {
    69.             if (m_side == SIDE.Mid)
    70.             {
    71.                 NewXpos = XValue;
    72.                 m_side = SIDE.Right;
    73.             }
    74.             else if (m_side == SIDE.Left)
    75.             {
    76.                 NewXpos = 0;
    77.                 m_side = SIDE.Mid;
    78.             }
    79.         }
    80.         x = Mathf.Lerp(x, NewXpos, Time.deltaTime * speeddodge);
    81.         Vector3 MoveVector = new Vector3(x - transform.position.x, y * Time.deltaTime, FwdSpeed * Time.deltaTime); ;
    82.         m_char.Move(MoveVector);
    83.         Jump();
    84.         Roll();
    85.  
    86.     }
    87.     public void Jump()
    88.     {
    89.         if (m_char.isGrounded)
    90.         {
    91.           Injump = false;
    92.             if (Swipeup)
    93.             {
    94.                 y = JumpPower;
    95.                 Injump = true;
    96.  
    97.             }
    98.         }
    99.         else
    100.         {
    101.             y -= JumpPower * 2 * Time.deltaTime;
    102.             if (m_char.velocity.y < 2f)
    103.             {
    104.  
    105.             }
    106.  
    107.         }
    108.     }
    109.     internal float RollCounter;
    110.     public void Roll()
    111.     {
    112.         RollCounter -= Time.deltaTime;
    113.         if(RollCounter <= 0)
    114.         {
    115.             RollCounter = 0f;
    116.             m_char.center = new Vector3(0, ColCenterY, 0);
    117.             m_char.height = ColHight;
    118.             InRoll = false;
    119.         }
    120.         if (Swipedown)
    121.         {
    122.             RollCounter = 0.2f;
    123.             y -= 10f;
    124.             m_char.center = new Vector3(0, ColCenterY/2f, 0);
    125.             m_char.height = ColHight/2f;
    126.             InRoll = true;
    127.             Injump = false;
    128.          
    129.  
    130.         }
    131.     }
    132. }
    133.  
     
  3. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    I want it to move a little smoothly so ill send a video here and it just teleports I just want it to move slowly
     
  4. BPPHarv

    BPPHarv

    Joined:
    Jun 9, 2012
    Posts:
    318
    Your character is teleporting because the calculation you're applying does not take the concept of time into account.
    What you need is to calculate the new position each frame / physics frame instead of the arbitrary amount you're adding each cycle.

    try something like this
    Code (CSharp):
    1.  
    2.       if (Input.GetKeyDown("w"))
    3.         {
    4.                transform.Translate(new Vector3(0, 0, 1) * Time.deltaTime);
    5.         }
    6.  
    in your update cycle instead.
     
  5. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    thx I'll try that
     
  6. Havyx

    Havyx

    Joined:
    Oct 20, 2020
    Posts:
    140
    GetKeyDown only returns true on the frame it was pressed - hence it will only trigger once. Use GetKey instead.

    https://docs.unity3d.com/ScriptReference/Input.GetKey.html

    "Returns true while the user holds down the key identified by name."


    Code (CSharp):
    1.  
    2. transform.Translate(Vector3.forward * Time.deltaTime * movementSpeed);
    3.  
     
  7. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    I want to use GetKeyDown because I want my character to move somwhere each time I tap so 20 units every time I tap wasd I just want it to move smoothly each time I hit wasd
     
  8. Havyx

    Havyx

    Joined:
    Oct 20, 2020
    Posts:
    140
    Then your issue is slightly more complex. You want to take a single input within a frame and translate it to smooth movement, right? This means you're going to have to do something over x seconds.

    https://docs.unity3d.com/ScriptReference/Vector3.Lerp.html

    Linear interpolate between two points (the starting position and ending position)

    Code (CSharp):
    1. public static Vector3 Lerp(Vector3 a, Vector3 b, float t);
    But you're probably going to have to trigger it within a coroutine.

    Something like this should move the player forward 1 unit linearly interpolated over 45 frames.

    Code (CSharp):
    1. public class ExampleClass : MonoBehaviour
    2. {
    3.     public int interpolationFramesCount = 45;
    4.     int elapsedFrames = 0;
    5.  
    6.     private bool hasReachedDestination;
    7.     private bool isMoving;
    8.  
    9.     private void Update()
    10.     {
    11.         if (Input.GetKeyDown(KeyCode.W))
    12.         {
    13.             if (!isMoving)
    14.             {
    15.                 isMoving = true;
    16.             }
    17.         }
    18.  
    19.         if (isMoving)
    20.         {
    21.             if (!hasReachedDestination)
    22.             {
    23.                 StartCoroutine(Move());
    24.             }
    25.         }
    26.     }
    27.  
    28.     private IEnumerator Move()
    29.     {
    30.         float interpolationRatio = (float)elapsedFrames / interpolationFramesCount;
    31.  
    32.         Vector3 interpolatedPosition = Vector3.Lerp(0, 0, 0, 0, 0, 1, interpolationRatio);
    33.  
    34.         if (elapsedFrames < interpolationFramesCount)
    35.         {
    36.             elapsedFrames = elapsedFrames + 1;
    37.         }
    38.         else
    39.         {
    40.             hasReachedDestination = true;
    41.             isMoving = false;
    42.             elapsedFrames = 0;
    43.         }
    44.  
    45.     }
    46. }
    you could also use a slightly different method

    Code (CSharp):
    1. public class ExampleClass : MonoBehaviour
    2. {
    3.     // Transforms to act as start and end markers for the journey.
    4.     public Transform startMarker;
    5.     public Transform endMarker;
    6.  
    7.     // Movement speed in units per second.
    8.     public float speed = 1.0F;
    9.  
    10.     // Time when the movement started.
    11.     private float startTime;
    12.  
    13.     // Total distance between the markers.
    14.     private float journeyLength;
    15.  
    16.     void Start()
    17.     {
    18.         // Keep a note of the time the movement started.
    19.         startTime = Time.time;
    20.  
    21.         // Calculate the journey length.
    22.         journeyLength = Vector3.Distance(startMarker.position, endMarker.position);
    23.     }
    24.  
    25.     // Move to the target end position.
    26.     void Update()
    27.     {
    28.         // Distance moved equals elapsed time times speed..
    29.         float distCovered = (Time.time - startTime) * speed;
    30.  
    31.         // Fraction of journey completed equals current distance divided by total distance.
    32.         float fractionOfJourney = distCovered / journeyLength;
    33.  
    34.         // Set our position as a fraction of the distance between the markers.
    35.         transform.position = Vector3.Lerp(startMarker.position, endMarker.position, fractionOfJourney);
    36.     }
    37. }
     
  9. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    thx Ill try that
     
  10. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    ok I have a couple errors

    PlayerController.Move(): not all code paths return a value

    no overload for method Lerp takes 7 arguments
     
  11. Havyx

    Havyx

    Joined:
    Oct 20, 2020
    Posts:
    140
    Code (CSharp):
    1. Vector3 interpolatedPosition = Vector3.Lerp(0, 0, 0, 0, 0, 1, interpolationRatio);
    Yeah I forgot about this. You need to pass it a starting transform and an end transform.

    This might work for moving forward.

    Code (CSharp):
    1. Vector3 interpolatedPosition = Vector3.Lerp(transform.position, Vector3.forward, interpolationRatio);
    if they press "a"

    Code (CSharp):
    1. Vector3 interpolatedPosition = Vector3.Lerp(transform.position, Vector3.left, interpolationRatio);
    "d"

    Code (CSharp):
    1. Vector3 interpolatedPosition = Vector3.Lerp(transform.position, Vector3.right, interpolationRatio);
    If that doesn't work you are going to need to take the current position and add an arbitrary distance on yourself for the end position (maybe something like this). but you would have to account for which direction you are going.

    destination = transform.position + new Vector3(transform.position.x, transform.position.y, transform.position.z + 1)
     
  12. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    alright ill try that but what about the Move() thing it says it needs to return a value is it just because of the error or is that another problem
     
  13. Havyx

    Havyx

    Joined:
    Oct 20, 2020
    Posts:
    140

    The error was because of this

    Code (CSharp):
    1. Vector3 interpolatedPosition = Vector3.Lerp([B][U]0, 0, 0, 0, 0, 1[/U][/B], interpolationRatio);
    It's incorrect syntax. Look at the error you posted:

    "no overload for method Lerp takes 7 arguments"

    It thinks you are trying to pass 7 arguments when it needs to be 3.


    transform.position will return a value in the format of (X, X, X)

    Vector3.forward is shorthand for (0, 0, 1).

    Code (CSharp):
    1. Vector3 interpolatedPosition = Vector3.Lerp(transform.position, Vector3.forward, interpolationRatio);
     
  14. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    ok so there is another error for the IEnumerator Move() I am a little new to unity so I do not know what the error means do I have to add a return value or
     
  15. Havyx

    Havyx

    Joined:
    Oct 20, 2020
    Posts:
    140
    oh yeah that was my mistake again. Coroutines expect a return (either null or WaitForSeconds)

     
  16. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    oh I was just about to do that thank you
     
  17. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    ok so there are no errors however the character does not move the interpolated position variable is not used is it? that could be a problem

    I might also just try a for loop and see if that works
     
  18. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    also I will show you the code here
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerController : MonoBehaviour
    6. {
    7.     public int interpolationFramesCount = 45;
    8.     int elapsedFrames = 0;
    9.  
    10.     private bool hasReachedDestination;
    11.     private bool isMoving;
    12.  
    13.     private void Update()
    14.     {
    15.         if (Input.GetKeyDown(KeyCode.W))
    16.         {
    17.             if (!isMoving)
    18.             {
    19.                 isMoving = true;
    20.             }
    21.         }
    22.  
    23.         if (isMoving)
    24.         {
    25.             if (!hasReachedDestination)
    26.             {
    27.                 StartCoroutine(Move());
    28.             }
    29.         }
    30.     }
    31.  
    32.     private IEnumerator Move()
    33.     {
    34.         float interpolationRatio = (float)elapsedFrames / interpolationFramesCount;
    35.  
    36.         Vector3 interpolatedPosition = Vector3.Lerp(transform.position, Vector3.forward, interpolationRatio);
    37.  
    38.         if (elapsedFrames < interpolationFramesCount)
    39.         {
    40.             elapsedFrames = elapsedFrames + 1;
    41.         }
    42.         else
    43.         {
    44.             hasReachedDestination = true;
    45.             isMoving = false;
    46.             elapsedFrames = 0;
    47.         }
    48.  
    49.         yield return null;
    50.  
    51.     }
    52. }
    53.  
    the character also does not move is there something I did wrong or am I just stupid and not noticing the obvious
     
  19. Havyx

    Havyx

    Joined:
    Oct 20, 2020
    Posts:
    140
    Not sure. It can sometimes be difficult as I just wrote it without testing. The best thing to do would be to use debug log to check each step is actually being called.

    For example, debug log something after the w key is pressed, then debug log something else just before isMoving is set to true... then debug log something just before the coroutine starts... then debug log something in the coroutine.

    This should indicate where the problem is.
     
  20. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,749
    You need to reason through the code.

    If you press W it sets isMoving true.

    Then if isMoving is true it starts a coroutine.

    The next frame in Update() (which is where you put this) it will AGAIN start ANOTHER coroutine.

    Why will it do that? Because iMoving is still true!

    You do not clear isMoving until the elapsed time has passed.

    None of this will ever work properly the way this is architected. You absolutely do not need a coroutine, and you CERTAINLY do not want a fresh one started every frame.

    I'm not sure what you are trying to do but this sounds like SUPER SUPER SUPER simple stuff, covered by literally THOUSANDS of Youtube character movement tutorials out there. I suggest you set this project aside and go legitimately work through two or three very simple movement tutorials and get familiar with the different approaches to doing this stuff. Otherwise you are going to thrash endlessly with this stuff.

    ALSO, feel free to take a look around the movement examples in my proximity_buttons package. Don't use them in your code until you understand them. They're really simple, honest.

    proximity_buttons is presently hosted at these locations:

    https://bitbucket.org/kurtdekker/proximity_buttons

    https://github.com/kurtdekker/proximity_buttons

    https://gitlab.com/kurtdekker/proximity_buttons

    https://sourceforge.net/projects/proximity-buttons/
     
    bobisgod234 and Vharz like this.
  21. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    ok ill check it out
     
  22. Havyx

    Havyx

    Joined:
    Oct 20, 2020
    Posts:
    140
    Yeah this was my bad... I think I had been awake for 20+ hours when I gave OP the original code.

    This. No idea what I was thinking using a coroutine.

    Try this. It only allows you to move in one direction, one unit at a time and interpolates between the current player position and destination.

    Code (CSharp):
    1. namespace Example
    2. {
    3.     public class MoveTest : MonoBehaviour
    4.     {
    5.         public Vector3 targetPosition;
    6.  
    7.         public bool isMoving;
    8.         public bool movePlayer;
    9.  
    10.         public float movementSpeed = 0.1f;
    11.  
    12.         void Update()
    13.         {
    14.             if (movePlayer)
    15.             {
    16.                 // get the distance between the player and target position
    17.                 float distanceLeftToDestination = Vector3.Distance(targetPosition, transform.position);
    18.  
    19.                 // account for the floating point inaccuracy. Player transform position is unlikely to exactly
    20.                 // match the destination position.
    21.                 if (distanceLeftToDestination < 0.1f)
    22.                 {
    23.                     movePlayer = false;
    24.                     isMoving = false;
    25.                 }
    26.  
    27.                 // keep moving the player towards the destination
    28.                 else
    29.                 {
    30.                     transform.position = Vector3.Lerp(transform.position, targetPosition, movementSpeed);
    31.                 }
    32.             }
    33.          
    34.             // Forward
    35.             if (Input.GetKeyDown(KeyCode.W))
    36.             {
    37.                 if (!isMoving)
    38.                 {
    39.                     isMoving = true;
    40.                     targetPosition = transform.position + new Vector3(0, 0, 1);
    41.                     movePlayer = true;
    42.                 }
    43.             }
    44.  
    45.             // Back
    46.             if (Input.GetKeyDown(KeyCode.S))
    47.             {
    48.                 if (!isMoving)
    49.                 {
    50.                     isMoving = true;
    51.                     targetPosition = transform.position + new Vector3(0, 0, -1);
    52.                     movePlayer = true;
    53.                 }
    54.             }
    55.  
    56.             // Left
    57.             if (Input.GetKeyDown(KeyCode.A))
    58.             {
    59.                 if (!isMoving)
    60.                 {
    61.                     isMoving = true;
    62.                     targetPosition = transform.position + new Vector3(-1, 0, 0);
    63.                     movePlayer = true;
    64.                 }
    65.             }
    66.  
    67.             // Right
    68.             if (Input.GetKeyDown(KeyCode.D))
    69.             {
    70.                 if (!isMoving)
    71.                 {
    72.                     isMoving = true;
    73.                     targetPosition = transform.position + new Vector3(1, 0, 0);
    74.                     movePlayer = true;
    75.                 }
    76.             }
    77.         }
    78.     }
    79. }
     
  23. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    thx ill try that
     
  24. seanyeet6

    seanyeet6

    Joined:
    Jan 16, 2021
    Posts:
    28
    yo thank u so much I would've never thought of that thank u