Vector3.MoveTowards()无法与TouchInputs一起使用

时间:2019-02-27 16:36:05

标签: c# unity3d

我正在尝试为游戏添加功能,以使具有 containerTransform 的对象可以根据触摸输入向左或向右移动720f。我使用了 Vector3.MoveTowards(),但是无论何时向右或向左滑动,它都显示**来回晃动,而不是向右或向左正确过渡720f。我不确定我的逻辑哪里出了问题。这是完整的代码。我正在寻求您的帮助。谢谢

private Vector2 startPosition;
private Vector2 endPosition;

public Transform containerTransform;
public float speed;
public float SoftZone = 20f;
//soft zone is the distance upto which the swipe wont work, so swipe length less than it wont trigger the function;

private bool SwipeLeft;
private bool SwipeRight;
private bool boolean;

private Vector3 currentLocation;
private Vector3 endLocation;

void Start()
{
    currentLocation = containerTransform.position;
    endLocation = containerTransform.position;
}


void Update()
{

    if(SwipeLeft) {

        containerTransform.position = Vector3.MoveTowards(

            currentLocation, 
            endLocation,
            Time.deltaTime * speed
            );

        if(containerTransform.position == endLocation) {

            SwipeLeft = false;
            currentLocation = endLocation;

            print("swipeleft ends");
        }
    }

    if(SwipeRight) {

        containerTransform.position = Vector3.MoveTowards(

            currentLocation, 
            endLocation,
            Time.deltaTime * speed
            );

        if(containerTransform.position == endLocation) {

            SwipeRight = false;
            currentLocation = endLocation;

            print("swiperight ends");
        }
    }

    SwipeCheck ();
}

void SwipeCheck () {

    /*if (!SwipeConfirmed){*/

 foreach (Touch touch in Input.touches)
    {
        if(touch.phase == TouchPhase.Began)
        {
            startPosition = touch.position;
            endPosition = touch.position;

            boolean = true;
        }

        if (touch.phase == TouchPhase.Moved)
        {
            endPosition = touch.position;
        }

        if (touch.phase == TouchPhase.Ended ||
            touch.phase == TouchPhase.Canceled &&
            boolean == true)
        {
            if (startPosition.x - endPosition.x >= SoftZone)
            {

                SwipeLeft = true;
                print("left");

                endLocation += new Vector3(

                    endLocation.x - 720f, 
                    endLocation.y, 
                    endLocation.z
                );

            }
            else if(startPosition.x - endPosition.x <= -SoftZone)
            {   

                SwipeRight = true;
                print("right");

                endLocation += new Vector3(

                    endLocation.x + 720f, 
                    endLocation.y, 
                    endLocation.z
                );
                boolean = false;
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

首先,Touch.position给您

  

触摸在像素坐标中的位置。

为了将其用于transform.position,您必须像使用Camera.ScreenToWorldPoint一样将它们转换为世界空间3D坐标

var worldPosition = Camera.main.ScreenToWorldPoint(new Vector3(touch.position.x, touch.position.y, distanceToCamera);

distanceToCamera是一个值的情况下,您必须定义/计算以确定该点应该在相机前面多远。


注意

如果您像在Update中那样经常使用它,则应该存储Camera并像这样重用引用:

private Camera cam;

private void Awake ()
{
    cam = Camera.main;
}

//...

var worldPosition = cam.ScreenToWorldPoint( ... );

主要问题

您正在使用

Vector3.MoveTowards(currentLocation, endLocation, speed * Time.deltaTime);

这将始终从currentLocation开始新的移动,因此您离currentLocation的距离不得超过一个步骤/帧。

请使用对象的实际当前位置

containerTransform.position = Vector3.MoveTowards(containerTransform.position, endPosition, speed * Time.deltaTime);

您的代码SwipeLeftSwipeRight实际上执行相同的操作,因此您只需删除其中一个块即可。

if (Swipe)
{
    containerTransform.position = Vector3.MoveTowards(containerTransform.position, endPosition, speed * Time.deltaTime);

    if (containerTransform.position == endLocation)
    {
        Swipe = false;
        currentLocation = endLocation;

        print("swipe ends");
    }
}

并且仅设置Swipe = true;


但是,我建议您使用Coroutines而不是在Update中做一些事情,因为使用StartCoroutineStopCoroutine可以更好地控制它们,并在您不使用的情况下传递您的价值不需要局部变量currentLocationendLocation

看起来像

// Makes sure only one scrolling process is running at a time
private bool isScrolling;

private IEnumerator MoveTo(Vector3 targetPosition)
{
    if (isScrolling) yield break;

    isScrolling = true;
    while (containerTransform.position != targetPosition)
    {
        containerTransform.position = Vector3.MoveTowards(containerTransform.position, endPosition, speed * Time.deltaTime);

        yield return null;
    }

    isScrolling = false;
    print("Swipe ends");
}

如果您想在一定时间内滑动,无论距离多远,都可以使用Vector3.Lerp

public float swipeDuration;

private IEnumerator MoveTo(Vector3 targetPosition)
{
    if (isScrolling) yield break;

    isScrolling = true;

    var currentPosition = containerTransform.position;

    var timePassed = 0.0f;

    while (timePassed < swipeDuration)
    {
        var lerpFactor = timePassed / swipeDuration;

        containerTransform.position = Vector3.Lerp(currentPosition, endPosition, lerpFactor);

        yield return null;
    }

    // To be sure set a fixed end position
    containerTransform.position = endPosition;

    isScrolling = false;
    print("Swipe ends");
}

SwipeCheck()中确认您的代码以使用新的协程。

StartCoroutine (MoveTo(endLocationWorldPoint));