繁体   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