Как заставить Rigidbody 2D двигаться в направлении, в котором пользователь провел пальцем? - PullRequest
0 голосов
/ 20 марта 2020

Используя Unity 2D и c#, я пытаюсь сделать так, чтобы игровой объект в мобильной игре двигался непрерывно и плавно в направлении, в котором проводил пользователь. Код ниже - это то, что я пытался сделать доберись до работы, и когда бы я ни запускал, ничего не происходит Игровой объект просто остается на месте всякий раз, когда я провожу пальцем. Я довольно новичок в такого рода вещах, поэтому у меня проблемы с выяснением, в чем проблема. Я думаю, что это как-то связано с операторами if и else из строк 38–62, но я не совсем уверен. Большое спасибо за вашу помощь.

private Vector3 fp;   //First touch position
private Vector3 lp;   //Last touch position

private float dragDistance;  //minimum distance for a swipe to be registered
private float speed = 10;

private Rigidbody2D rb;
private Vector2 moveVelocity;

void Start() {
    dragDistance = Screen.height * 5 / 100; //dragDistance is 5% height of the screen
    rb = GetComponent<Rigidbody2D>();
}

void Update() {

    if (Input.touchCount == 1) // user is touching the screen with a single touch
    {
        Touch touch = Input.GetTouch(0); // get the touch
        if (touch.phase == TouchPhase.Began) //check for the first touch
        {
            fp = touch.position;
            lp = touch.position;
        }
        else if (touch.phase == TouchPhase.Moved) // update the last position based on where they moved
        {
            lp = touch.position;
        }
        else if (touch.phase == TouchPhase.Ended) //check if the finger is removed from the screen
        {
            lp = touch.position;  //last touch position. Ommitted if you use list

            //Check if drag distance is greater than ?% of the screen height
            if (Mathf.Abs(lp.x - fp.x) > dragDistance || Mathf.Abs(lp.y - fp.y) > dragDistance)
            {//It's a drag
             //check if the drag is vertical or horizontal

                if (Mathf.Abs(lp.x - fp.x) > Mathf.Abs(lp.y - fp.y))
                {   //If the horizontal movement is greater than the vertical movement...
                    if ((lp.x > fp.x))  //If the movement was to the right)
                    {   //Right swipe
                        Vector2 moveInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
                        moveVelocity = moveInput.normalized * speed;
                    }
                    else
                    {   //Left swipe
                        Vector2 moveInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
                        moveVelocity = moveInput.normalized * speed;
                    }
                }
                else
                {   //the vertical movement is greater than the horizontal movement
                    if (lp.y > fp.y)  //If the movement was up
                    {   //Up swipe
                        Vector2 moveInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
                        moveVelocity = moveInput.normalized * speed;
                    }
                    else
                    {   //Down swipe
                        Vector2 moveInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
                        moveVelocity = moveInput.normalized * speed;
                    }
                }

            }
        }
    }

}

void FixedUpdate() {
    rb.MovePosition(rb.position + moveVelocity * Time.fixedDeltaTime);
}

1 Ответ

0 голосов
/ 20 марта 2020

Прежде всего все ваши случаи точно равны:

if (Mathf.Abs(lp.x - fp.x) > Mathf.Abs(lp.y - fp.y))
{   //If the horizontal movement is greater than the vertical movement...
    if ((lp.x > fp.x))  //If the movement was to the right)
    {   //Right swipe
        Vector2 moveInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
        moveVelocity = moveInput.normalized * speed;
    }
    else
    {   //Left swipe
        Vector2 moveInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
        moveVelocity = moveInput.normalized * speed;
    }
}
else
{   //the vertical movement is greater than the horizontal movement
    if (lp.y > fp.y)  //If the movement was up
    {   //Up swipe
        Vector2 moveInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
        moveVelocity = moveInput.normalized * speed;
    }
    else
    {   //Down swipe
        Vector2 moveInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
        moveVelocity = moveInput.normalized * speed;
    }
}

Все они используют одинаковые две строки

Vector2 moveInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
moveVelocity = moveInput.normalized * speed;

Я предполагаю, что Input.GetAxisRaw("Horizontal") и Input.GetAxisRaw("Vertical") просто всегда 0, и поэтому никакого движения не происходит вообще. Насколько я знаю, это работает только для ввода с клавиатуры и мыши, а не для касаний.

Не лучше ли вы в соответствии с вашим направлением движения, а, например,

if (Mathf.Abs(lp.x - fp.x) > Mathf.Abs(lp.y - fp.y))
{   
    //If the horizontal movement is greater than the vertical movement...
    if (lp.x > fp.x)  //If the movement was to the right)
    {   //Right swipe
        moveVelocity = Vector2.right;
    }
    else
    {   //Left swipe
        moveVelocity = Vector2.left;
    }
}
else
{   //the vertical movement is greater than the horizontal movement
    if (lp.y > fp.y)  //If the movement was up
    {   //Up swipe
        moveVelocity = Vector2.up;
    }
    else
    {   //Down swipe
        moveVelocity = Vector2.down;
    }
}

А затем

void FixedUpdate() 
{
    rb.MovePosition(rb.position + moveVelocity * speed * Time.deltaTime);
}

Обратите внимание, что вместо Time.fixedDeltaTime

Для чтения времени дельты рекомендуется использовать Time.deltaTime вместо этого, поскольку он автоматически возвращает правильную дельту время, если вы находитесь внутри функции FixedUpdate или Update.


В качестве альтернативы вы также можете напрямую назначить rb.velocity

if (Mathf.Abs(lp.x - fp.x) > Mathf.Abs(lp.y - fp.y))
{   
    //If the horizontal movement is greater than the vertical movement...
    if (lp.x > fp.x)  //If the movement was to the right)
    {   //Right swipe
        rb.velocity = Vector2.right * speed;
    }
    else
    {   //Left swipe
        rb.velocity = Vector2.left * speed;;
    }
}
else
{   //the vertical movement is greater than the horizontal movement
    if (lp.y > fp.y)  //If the movement was up
    {   //Up swipe
        rb.velocity = Vector2.up * speed;;
    }
    else
    {   //Down swipe
        rb.velocity = Vector2.down * speed;;
    }
}

без FixedUpdate. Поскольку вы здесь только изменяете velocity Rigidbody и не перемещаете его напрямую, это можно сделать в Update.


Общие примечания:

Вы должны используйте switch-case вместо

switch(touch.phase)
{
    case TouchPhase.Began:
        fp = touch.position;
        // No need to assign lp here actually
        // lp = touch.position;
        break;

    case TouchPhase.Ended:
        // lp could actually be a local variable - no need to make it a field
        var lp = touch.position;
        ...

        break;
}

Поскольку вы не используете значение lp, назначенное в TouchPhase.Moved, вы можете вообще пропустить этот блок.

Вы можете сделайте ваши if-else проверки на направление перемещения немного более читабельными / лучше поддерживающими, введя одну дополнительную переменную:

var lp = touch.position;
var difference = lp - fp;

if (difference.x > dragDistance || difference.y > dragDistance)
{
    if (Mathf.Abs(difference.x) > Mathf.Abs(difference.y))
    {
        if (difference.x > 0)
        {
            // Right swipe
        }
        else
        {   
            // Left swipe
        }
    }
    else
    {
        if (difference.y > 0)
        {
            // Up swipe
        }
        else
        {   
            // Down swipe
        }
    }
}
...