簡體   English   中英

如何使 Rigidbody 2D 沿用戶滑動的方向移動?

[英]How do I make a Rigidbody 2D move in the direction the user swiped in?

使用 Unity 2D 和 c#,我試圖讓手機游戲中的游戲對象能夠在用戶滑動的方向上連續平滑地移動。下面的代碼是我一直在嘗試開始工作的代碼我運行它,沒有任何反應。 每當我滑動時,游戲對象就會保持原位。 我對這種東西很陌生,所以我很難找出問題所在。 我認為這與第 38 到 62 行的 if 和 else 語句有關,但我不完全確定。 非常感謝你的幫助。

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);
}

首先,您的情況完全相同:

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 由於您在此處僅更改 Rigidbody 的velocity並且不直接移動它,因此可以在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;
}

由於您不使用在TouchPhase.Moved分配的lp值,因此您實際上可以完全跳過此塊。

您可以通過引入一個額外的變量來使您的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
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM