Search Unity

Moving 2D sprite is not smooth

Discussion in '2D' started by ryanzec, Jul 23, 2016.

  1. ryanzec

    ryanzec

    Joined:
    Jun 10, 2008
    Posts:
    696
    So I am starting out trying to create a top down 2D game that has grid based movement (like Pokemon) I have an implementation of movement functional however it is not really smooth:

    2d-movement-not-smooth.gif

    It seems to be janky when it stops the current MovePosition and starts the next one. What can I do to make this transition smooth while the key is being pressed?

    Here is the code:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PlayerController : MonoBehaviour {
    5.     public float speed = 5f;
    6.  
    7.     private bool isMoving = false;
    8.     private BoxCollider2D boxCollider;
    9.     private Rigidbody2D rigidbody;
    10.  
    11.     void Start() {
    12.         boxCollider = GetComponent<BoxCollider2D>();
    13.         rigidbody = GetComponent<Rigidbody2D>();
    14.     }
    15.  
    16.     void FixedUpdate() {
    17.         if (!isMoving) {
    18.             bool moveLeft = Input.GetKey(KeyCode.A);
    19.             bool moveDown = Input.GetKey(KeyCode.S);
    20.             bool moveRight = Input.GetKey(KeyCode.D);
    21.             bool moveUp = Input.GetKey(KeyCode.W);
    22.  
    23.             if (moveLeft || moveDown || moveUp || moveRight) {
    24.                 Vector3 move = new Vector3(0, 0, 0);
    25.  
    26.                 if (moveLeft) {
    27.                     move.x = -1;
    28.                 }
    29.  
    30.                 if (moveRight) {
    31.                     move.x = 1;
    32.                 }
    33.  
    34.                 if (move.x == 0) {
    35.                     if (moveUp) {
    36.                         move.y = 1;
    37.                     }
    38.  
    39.                     if (moveDown) {
    40.                         move.y = -1;
    41.                     }
    42.                 }
    43.  
    44.                 Vector3 end = transform.position + move;
    45.  
    46.                 boxCollider.enabled = false;
    47.                 RaycastHit2D hit = Physics2D.Linecast(transform.position, end);
    48.                 boxCollider.enabled = true;
    49.  
    50.                 if (hit.transform == null) {
    51.                     StartCoroutine(PerformMove(end));
    52.                 }
    53.             }
    54.         }
    55.     }
    56.  
    57.     protected IEnumerator PerformMove(Vector3 end) {
    58.         isMoving = true;
    59.         float squareRemainingDistance = (transform.position - end).sqrMagnitude;
    60.  
    61.         while (squareRemainingDistance > 0f) {
    62.             Vector3 newPosition = Vector3.MoveTowards(rigidbody.position, end, speed * Time.deltaTime);
    63.  
    64.             rigidbody.MovePosition(newPosition);
    65.  
    66.             squareRemainingDistance = (transform.position - end).sqrMagnitude;
    67.             yield return null;
    68.         }
    69.  
    70.         isMoving = false;
    71.     }
    72. }
    73.  
     
  2. Cherno

    Cherno

    Joined:
    Apr 7, 2013
    Posts:
    515
    Try setting the RB's velocity to Vector2.zero.
    Use Transform.Translate to move the RB.
     
  3. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    You should either be using forces to move your character with physics in FixedUpdate, or set the Transform's Position in Update.

    From the looks of it, you should be using Update because you're polling inputs, and not using physics.

    You do not need to use that coroutine every frame, because it will continuously be started every frame before it has a chance to move.

    If you want smooth movement, you want to move incrementally over time in Update.

    Try using this:
    Code (CSharp):
    1. private void Update(){
    2.     // check inputs etc.
    3.    
    4.     // move smoothly, never moving farther than maxSpeed in one frame.
    5.     transform.position = Vector3.MoveTowards(transform.position, endPosition, maxSpeed);
    6. }