我有一个要滑动的对象,例如,向上滑动时,该对象应从A点平稳地向前移动到B点,向右滑动则该对象平稳地向右移动...等>
为此,我尝试了 Lerp , MoveTowards 和 SmoothDamp ,但是每次对象刚从A点消失并出现在即刻到达B点。
因此,我使用协程为运动提供了时间,如下面的代码所示,有4种协程方法,每个方法都针对一个方向。我的问题是,在播放时,第一个动作正常,但是在第二次滑动时,对象没有到达目的地,第三个动作和对象也有一些奇怪的动作。
您能告诉我我的代码有什么问题吗?
以下是协程的移动方法:
public IEnumerator MoveForward()
{
Vector3 DestinationF = new Vector3(transform.position.x, transform.position.y, transform.position.z + DistanceF);
while (Vector3.Distance(transform.localPosition, DestinationF) > 0)
{
float totalMovementTimeF = 0.3f;
float currentMovementTimeF = 0f;
currentMovementTimeF += Time.deltaTime;
transform.localPosition = Vector3.Lerp(transform.position, DestinationF, currentMovementTimeF / totalMovementTimeF);
yield return null;
}
}
public IEnumerator MoveBackward()
{
Vector3 DestinationB = new Vector3(transform.position.x, transform.position.y, transform.position.z - DistanceB);
while (Vector3.Distance(transform.localPosition, DestinationB) > 0)
{
float totalMovementTimeB = 0.3f;
float currentMovementTimeB = 0f;
currentMovementTimeB += Time.deltaTime;
transform.localPosition = Vector3.Lerp(transform.position, DestinationB, currentMovementTimeB / totalMovementTimeB);
yield return null;
}
}
仍然有2个协程方法MoveRight()和MoveLeft()。
这是滑动方向的代码:
if (Input.GetMouseButtonDown(0))
{
//save began touch 2d point
firstPressPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y);
}
if (Input.GetMouseButtonUp(0))
{
//save ended touch 2d point
secondPressPos = new Vector3(Input.mousePosition.x, Input.mousePosition.y);
//create vector from the two points
currentSwipe = new Vector3(secondPressPos.x - firstPressPos.x, secondPressPos.y - firstPressPos.y);
//normalize the 2d vector
currentSwipe.Normalize();
// swipe up
if (currentSwipe.y > 0 && currentSwipe.x > -0.5f && currentSwipe.x < 0.5f)
{
StartCoroutine(MoveForward());
}
// swipe down
if (currentSwipe.y < 0 && currentSwipe.x > -0.5f && currentSwipe.x < 0.5f)
{
StartCoroutine(MoveBackward());
}
//swipe left
if (currentSwipe.x < 0 && currentSwipe.y > -0.5f && currentSwipe.y < 0.5f)
{
StartCoroutine(MoveLeft());
}
//swipe right
if (currentSwipe.x > 0 && currentSwipe.y > -0.5f && currentSwipe.y < 0.5f)
{
StartCoroutine(MoveRight());
}
}
答案 0 :(得分:1)
您的第一个协程之所以能够工作,是因为: Vector3 DestinationF =新的Vector3(transform.position.x,transform.position.y,transformationposition.z + DistanceF);
将得到一个正位置,因此,距离将大于0:
while (Vector3.Distance(transform.localPosition, DestinationF) > 0)
另一方面,从z值中减去distanceB:
Vector3 DestinationB = new Vector3(transform.position.x, transform.position.y, transform.position.z - DistanceB);
可能会产生负值,因此:
while (Vector3.Distance(transform.localPosition, DestinationB) > 0)
将从<0开始,因此永远不会满足该条件。检查您的状况。您要绝对值还是不等于0?
答案 1 :(得分:0)
问题是您从不到达目标。
您忍受的因素
currentMovementTimeF / totalMovementTimeF
意义不大,因为您将每一帧重置为
var currentMovementTimeF = Time.deltaTime;
在大多数情况下为< 0.3f
(这意味着您每秒只有约3帧),因此始终为
currentMovementTimeF < totalMovementTimeF
,因此
currentMovementTimeF / totalMovementTimeF < 1
因此,您始终在当前位置和目标之间开始新的插值。因此,距离越来越小,但实际上并没有到达最终位置(尽管看起来确实如此)。
另外,您在此处混合了position
和localPosition
,因此,如果GameObject
不在根目录下,甚至会变得更糟!
您想要使用的是MoveTowards
和某个speed
。 (基于位置)
// adjust these in the Inspector
public float speed;
public float MoveDistance;
public IEnumerator Move(Vector3 direction)
{
var destinaton = transform.position + direction * MoveDistance;
while (Vector3.Distance(transform.position, destinaton) > 0)
{
transform.position = Vector3.MoveTowards(transform.position, MoveDistance, Time.deltaTime* speed);
yield return null;
}
}
MoveTowards
确保没有超调。
或使用Lerp(基于时间)
// adjust these in the Inspector
public float totalMovementTime = 0.3f;
public float MoveDistance;
public IEnumerator Move(Vector3 direction)
{
var originalPosition = transform.position;
var destination = transform.position + direction * MoveDistance;
// here you could make it even more accurate
// by moving allways with the same speed
// regardless how far the object is from the target
//var moveDuration = totalMovementTime * Vector3.Distance(transform.position, destinaton);
// and than replacing totalMovementTime with moveDuration
var currentDuration = 0.0f;
while (currentDuration < totalMovementTime)
{
transform.position = Vector3.Lerp(originalPosition, destination, currentDuration / totalMovementTime);
currentDuration += Time.deltaTime;
yield return null;
}
// to be really sure set a fixed position in the end
transform.position = destinaton;
}
另一个问题是,您当前仍可以启动两个并发的协程,从而导致异常行为。您宁可每次启动类似新的
时都应中断协程if (currentSwipe.y > 0 && currentSwipe.x > -0.5f && currentSwipe.x < 0.5f)
{
// stop all current routines
stopAllCoroutines();
StartCoroutine(MoveForward());
}
或添加一个标志以仅运行一个例程,同时忽略输入:
private bool isSwiping;
public IEnumerator MoveForward()
{
if(isSwiping)
{
Debug.LogWarning("Already swiping -> ignored", this);
yield break;
}
isSwiping = true;
//...
isSwiping = false;
}