我正在实施特定类型的触控器。 玩家需要将手指放在屏幕上才能移动。 在不抬起手指的情况下,玩家可以在不同方向上滑动以在仍然移动的同时改变方向。 一旦手指抬起,玩家就会停止移动。
很难隔离特定滑动(即在屏幕上绘制的线条),忽略任何其他不打算划线的动作。 例如,当玩家的手指“静止”时进行轻微的手指动作,他们搞砸了我的算法。
我考虑了不同的方法,例如存储最后几次触摸并评估它们以确定是否有滑动,但无法正确实现。
这是我到目前为止所尝试的内容。大部分时间它运作良好,但通常玩家运动不稳定,并且与我的预期完全相反。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TouchInputHandler : AbstractInputHandler {
private const int SWIPE_MIN_DISTANCE = 35;
private Vector2 touchStartPoint;
private Vector2 touchMovePoint;
void Update () {
Touch[] touches = Input.touches;
if (touches.Length == 1) {
Touch firstTouch = touches [0];
if (firstTouch.phase == TouchPhase.Began) {
this.touchStartPoint = firstTouch.position;
fireNextDirectionChanged (currentDirection);
} else if (firstTouch.phase == TouchPhase.Moved) {
this.touchMovePoint = firstTouch.position;
if (Vector2.Distance(touchStartPoint, touchMovePoint) > SWIPE_MIN_DISTANCE) {
detectSwipeDirection ();
}
} else if (firstTouch.phase == TouchPhase.Stationary) {
touchStartPoint.x = touchMovePoint.x;
touchStartPoint.y = touchMovePoint.y;
} else if (firstTouch.phase == TouchPhase.Ended) {
fireNextDirectionChanged (Constants.Direction.NONE);
}
}
}
private void detectSwipeDirection() {
float xDiff = touchMovePoint.x - touchStartPoint.x;
float yDiff = touchMovePoint.y - touchStartPoint.y;
Constants.Direction nextDirection;
bool yGreater = Mathf.Abs(yDiff) >= Mathf.Abs(xDiff);
if (yGreater) {
// direction is up or down
nextDirection = yDiff < 0 ? Constants.Direction.DOWN : Constants.Direction.UP;
} else {
// direction is left or right
nextDirection = xDiff < 0 ? Constants.Direction.LEFT : Constants.Direction.RIGHT;
}
if (nextDirection != this.currentDirection)
{
fireNextDirectionChanged (nextDirection);
this.currentDirection = nextDirection;
}
}
}
答案 0 :(得分:0)
我想你只是忘了一行将前一个触摸位置设置为TouchPhase.Moved
块中的当前触摸位置。只需添加touchStartPoint = this.touchMovePoint;
它就可以工作(仅使用鼠标输入进行测试,但逻辑保持不变)。
我还评论了TouchPhase.Stationary
块:我觉得它像我之前建议的那样,但只有当手指完全不动时。最终代码如下所示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TouchInputHandler : AbstractInputHandler
{
private const int SWIPE_MIN_DISTANCE = 35;
private Vector2 touchStartPoint;
private Vector2 touchMovePoint;
void Update()
{
Touch[] touches = Input.touches;
if(touches.Length == 1)
{
Touch firstTouch = touches[0];
if(firstTouch.phase == TouchPhase.Began)
{
this.touchStartPoint = firstTouch.position;
this.currentDirection = Constants.Direction.NONE;
fireNextDirectionChanged(currentDirection);
}
else if(firstTouch.phase == TouchPhase.Moved)
{
this.touchMovePoint = firstTouch.position;
if(Vector2.Distance(touchStartPoint, touchMovePoint) > SWIPE_MIN_DISTANCE)
{
detectSwipeDirection();
}
touchStartPoint = this.touchMovePoint; // <= NEW !
}
//else if(firstTouch.phase == TouchPhase.Stationary)
//{
// touchStartPoint.x = touchMovePoint.x;
// touchStartPoint.y = touchMovePoint.y;
//}
else if(firstTouch.phase == TouchPhase.Ended)
{
this.currentDirection = Constants.Direction.NONE;
fireNextDirectionChanged(Constants.Direction.NONE);
}
}
}
private void detectSwipeDirection()
{
float xDiff = touchMovePoint.x - touchStartPoint.x;
float yDiff = touchMovePoint.y - touchStartPoint.y;
Constants.Direction nextDirection;
bool yGreater = Mathf.Abs(yDiff) >= Mathf.Abs(xDiff);
if(yGreater)
{
// direction is up or down
nextDirection = yDiff < 0 ? Constants.Direction.DOWN : Constants.Direction.UP;
}
else
{
// direction is left or right
nextDirection = xDiff < 0 ? Constants.Direction.LEFT : Constants.Direction.RIGHT;
}
if(nextDirection != this.currentDirection)
{
fireNextDirectionChanged(nextDirection);
this.currentDirection = nextDirection;
}
}
}
此外,当使用基于游戏距离的距离来检测滑动时,如果您想将项目移植到多个分辨率设备,我建议在某处添加Screen.width/height
比例(Start()
使用SWIPE_MIN_DISTANCE *= Screen.width / BASE_SCREEN_WIDTH
执行private const int BASE_SCREEN_WIDTH = 1024;
之类的操作。
希望这有帮助,