Move a rigidbody smoothly by swipe

Hi to all, i’m very new on unity and i’m facing my first problem.
On my 3d project i have a spheric rigidbody that will rolling constantly along z (on a big square rigidbody used as “floor”), and i would like to translate it on x axis (left and right) with swipe.
This is the sphere controller script:

public class PlayerController : MonoBehaviour
{
    public static PlayerController Instance { get; private set; }

    private Rigidbody rb;
    public float speed;

    void Start()
    {
        Instance = this;
        rb = GetComponent<Rigidbody>();
        speed = 20f;
    }

    private void FixedUpdate()
    {
        rb.AddForce(0f, 0f, speed, ForceMode.Acceleration);
    }

    public void MovePlayer(float movement)
    {
        StartCoroutine(MovePlayerCoroutine(movement));
    }

    private IEnumerator MovePlayerCoroutine(float movement)
    {
        rb.position = new Vector3(
          transform.position.x + (movement/ 20f),
          transform.position.y,
          transform.position.z);

        yield return null;

    }

(my rigidbody has mass, drag and angular drag 1, use gravity and interpolate).

this is the script (attached to Main Camera object) for detect left and righ swipe and move player:

public class SwipeController : MonoBehaviour
{
    // detected position on last frame
    private Vector3 lastTouchPosition;
    // detected position on current frame
    private Vector3 currentTouchPosition;
    //minimum distance for a swipe to be detected
    private float dragDistance;

    void Start()
    {
        // dragDistance will be a portion of screen
        dragDistance = Screen.width * 5 / 100;
    }

    private void Update()
    {
        foreach (Touch touch in Input.touches)  //use loop to detect more than one swipe
        {

            if (touch.phase == TouchPhase.Began)
            {
                // first touch on screen
                lastTouchPosition = touch.position;
            }
            else if (touch.phase == TouchPhase.Moved)
            {
                currentTouchPosition = touch.position;
                if (Mathf.Abs(currentTouchPosition.x - lastTouchPosition.x) > dragDistance || Mathf.Abs(currentTouchPosition.y - lastTouchPosition.y) > dragDistance)
                {//It's a drag

                    PlayerController.Instance.MovePlayer(currentTouchPosition.x - lastTouchPosition.x);      
                    if ((currentTouchPosition.x > lastTouchPosition.x))  
                    {   //Right swipe
                        Debug.Log("Right Swipe");
                        lastTouchPosition = currentTouchPosition;
                    }
                    else
                    {   //Left swipe
                        Debug.Log("Left Swipe");
                        lastTouchPosition = currentTouchPosition;
                    }
                }
            }
            else if (touch.phase == TouchPhase.Ended)
            {
                // reset positions
                lastTouchPosition = currentTouchPosition = new Vector3();
            }
        }
    }
}

This code works but the movement is not smooth (it seems that sphere jump directly on new position). Whats the problem?

hello, that happens because you are teleporting inside the corroutine the object from one position to another. first i would suggest not using rb.position since thats just teleporting the object and collisions will get affected, you could be using rb.velocity for example and give the object your desired velocity in the x axis

rb.velocity = Vector3.right * speed;

but this will not make the object move to a position just will add a force and for stopping that object you will have to force the velocity in x axis to be 0 if swipped ended, if you want to use rb.position you can use the coroutine (since right now you are using it just as a method) you can add a for inside the coroutine and rather than moving once to that position iterate littlle by little.

After some tests i’ve implemented this (i’ve excluded to change velocity):

private IEnumerator MovePlayerCoroutine(float movement)
    {

        Vector3 targetPosition = new Vector3(transform.position.x +movement, transform.position.y, transform.position.z);

        Vector3 direction = (targetPosition - transform.position).normalized;

        rb.MovePosition(transform.position + direction * 20f * Time.deltaTime);
     yield return null;
    }

but movement is still not smooth (but smoother than my first implementation).

i think you want something more like this

UnityDevelopment.BowlMaster.BallDragLaunch

if (inputValue > 0)
{

                rigidbody.AddForce(new Vector3(0.5f, 0, 0)* smoothnessValue);
                //Jump(Vector3.left);
            }
            else if (inputValue < 0)
            {

                rigidbody.AddForce(new Vector3(-0.5f, 0, 0) * smoothnessValue);
                //Jump(Vector3.right);
            }