移动游戏物体随着时间的推移

问题描述:

我从斯威夫特SpriteKit背景,其中移动精灵的X位置是直线前进为如下运行行动学习统一:移动游戏物体随着时间的推移

let moveLeft = SKAction.moveToX(self.frame.width/5, duration: 1.0) 
let delayAction = SKAction.waitForDuration(1.0) 
let handSequence = SKAction.sequence([delayAction, moveLeft]) 
sprite.runAction(handSequence) 

我想知道的相同或相似在特定的持续时间(例如,秒)中将精灵移动到特定位置的方式,其延迟不必在更新功能中调用。

+0

我强烈建议使用类似的ITween的扩展这种控制的动画 – caulitomaz

+1

@caulitomaz并不需要的ITween或插件that.He只需要学习Coroutune。 – Programmer

+1

不要在这里使用iTween,忘记了。 – Fattie

gjttt1的答案是接近这一点远远优于工作,但缺少了重要的功能和用于移动游戏对象是不可接受的使用WaitForSeconds()。您应该使用Lerp,CoroutineTime.deltaTime的组合。你必须理解这些东西才能够从Unity中的Script中完成动画。

public GameObject objectectA; 
public GameObject objectectB; 

void Start() 
{ 
    StartCoroutine(moveToX(objectectA.transform, objectectB.transform.position, 1.0f)); 
} 


bool isMoving = false; 

IEnumerator moveToX(Transform fromPosition, Vector3 toPosition, float duration) 
{ 
    //Make sure there is only one instance of this function running 
    if (isMoving) 
    { 
     yield break; ///exit if this is still running 
    } 
    isMoving = true; 

    float counter = 0; 

    //Get the current position of the object to be moved 
    Vector3 startPos = fromPosition.position; 

    while (counter < duration) 
    { 
     counter += Time.deltaTime; 
     fromPosition.position = Vector3.Lerp(startPos, toPosition, counter/duration); 
     yield return null; 
    } 

    isMoving = false; 
} 

类似的问题:SKAction.scaleXTo

+0

谢谢!也可以在'rotation'上使用'Vector3.Lerp',想象如果你想让对象从'startRotation'旋转到'endRotation'(x,y,z) – vikingsteve

+0

@vikingsteve是的。如果是增量旋转,则可以使用'Vector3.Lerp'来更改'transform.eulerAngles'。如果你只想从rotationA转到rotateB,那么'Quaternion.Lerp'应该用来改变'transform.rotation'。其余的代码保持不变。请参阅我的[other](https://*.com/a/37588536/3785314)该解决方案的答案。 – Programmer

+1

谢谢senpai! Unity线程是错误的.. –

您可以使用协程来做到这一点。要做到这一点,创建一个返回类型IEnumerator的功能,包括一个循环做你想要的:

private IEnumerator foo() 
{ 
    while(yourCondition) //for example check if two seconds has passed 
    { 
     //move the player on a per frame basis. 
     yeild return null; 
    } 
} 

然后,你可以通过使用StartCoroutine(foo())

这调用该函数每帧调用它它从上次停止的地方开始。因此在这个例子中,它在一帧上停止在yield return null,然后在下一帧重新开始:因此它每帧重复while循环中的代码。

如果你想暂停一段时间,那么你可以使用yield return WaitForSeconds(3)等待3秒钟。你也可以yield return其他的例程!这意味着当前例程将暂停并运行第二个协程,然后在第二个协程完成后再次拾取。

我建议您检查docs,因为他们做解释比我在这里可以

GIT1的答案是好的,但有,如果你不希望使用couritines另一种解决方案。

您可以使用InvokeRepeating重复触发某个功能。

float duration; //duration of movement 
float durationTime; //this will be the value used to check if Time.time passed the current duration set 

void Start() 
{ 
    StartMovement(); 
} 

void StartMovement() 
{ 
    InvokeRepeating("MovementFunction", Time.deltaTime, Time.deltaTime); //Time.deltaTime is the time passed between two frames 
    durationTime = Time.time + duration; //This is how long the invoke will repeat 
} 

void MovementFunction() 
{ 
    if(durationTime > Time.time) 
    { 
     //Movement 
    } 
    else 
    { 
     CancelInvoke("MovementFunction"); //Stop the invoking of this function 
     return; 
    } 
} 
+1

确实,这工作得很好,每个人都应该学会使用InvokeRepeating。通常,在这里使用协程就是惯用的。 – Fattie