随时间移动游戏对象
Move GameObject over time
我正在从 Swift SpriteKit 背景学习 Unity,其中移动精灵的 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)
我想知道将精灵移动到特定位置持续特定持续时间(例如,一秒)的等效或类似方法,并且不必在更新函数中调用延迟。
您可以使用协程来执行此操作。为此,创建一个 returns 类型 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,因为他们在这方面的解释比我在这里做得更好
gjttt1 的答案很接近,但缺少重要功能,并且使用 WaitForSeconds()
移动 GameObject 是不可接受的。您应该使用 Lerp
、Coroutine
和 Time.deltaTime
的组合。您必须了解这些内容才能在 Unity 中通过脚本制作动画。
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
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;
}
}
我正在从 Swift SpriteKit 背景学习 Unity,其中移动精灵的 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)
我想知道将精灵移动到特定位置持续特定持续时间(例如,一秒)的等效或类似方法,并且不必在更新函数中调用延迟。
您可以使用协程来执行此操作。为此,创建一个 returns 类型 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,因为他们在这方面的解释比我在这里做得更好
gjttt1 的答案很接近,但缺少重要功能,并且使用 WaitForSeconds()
移动 GameObject 是不可接受的。您应该使用 Lerp
、Coroutine
和 Time.deltaTime
的组合。您必须了解这些内容才能在 Unity 中通过脚本制作动画。
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
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;
}
}