【问题标题】:Vector3.MoveTowards() is not working with TouchInputsVector3.MoveTowards() 不适用于 TouchInputs
【发布时间】:2019-07-21 10:59:04
【问题描述】:

我正在尝试为我的游戏添加一个功能,以便具有 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;
            }
        }
    }
}

【问题讨论】:

  • 您对MoveTowards 或从滑动逻辑中获取Vector3 有疑问吗? Minimal, Complete, and Verifiable 将有助于确定您的问题真正出在哪里。我建议使用带有调试语句的代码来显示您的计算,然后将输出复制粘贴到您的问题中。

标签: c# unity3d


【解决方案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 可以更好地控制它们,并且将值传递给你不需要局部变量 @987654341 @和endLocation

看起来像

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 2017-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多