随着时间的推移移动游戏对象

Posted

技术标签:

【中文标题】随着时间的推移移动游戏对象【英文标题】:Move GameObject over time 【发布时间】:2016-04-25 20:17:43 【问题描述】:

我正在从 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)

我想知道一种等效或类似的方法,可以将精灵移动到特定位置并持续特定的持续时间(例如,一秒),延迟时间不必在更新函数中调用。

【问题讨论】:

我强烈推荐使用像 iTween 这样的扩展来实现这种受控动画 @caulitomaz 不需要 iTween 或插件。他只需要学习 Coroutune。 不要在这里使用 iTween,算了。 嗨@Nullititiousness。从根本上来说,Unity 是一个游戏引擎,因此:是一个基于框架的系统。一切都与框架有关。 (确实请注意,在 ios 中,由于它基本上不是基于框架的,因此他们会搞砸并做“类似框架”的事情,以弥补它不是基于框架的系统这一事实,但有时您需要“那样”的东西。 ) 无论如何,如果你说“我想‘移动’一些东西”。你实际上在说什么?你是说你想在每一帧都做一些事情——对吧?如果你开始这样想,那就很容易了。 【参考方案1】:

gjttt1 的答案很接近,但缺少重要功能,并且使用 WaitForSeconds() 移动 GameObject 是不可接受的。您应该使用LerpCoroutineTime.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

【讨论】:

谢谢! Vector3.Lerp 也可以用在rotation 上,想象一下如果你想让对象也从startRotation 旋转到endRotation (x,y,z) @vikingsteve 是的。如果是增量旋转,您可以使用Vector3.Lerp 更改transform.eulerAngles。如果您只想从rotationA 转到rotationB,则应使用Quaternion.Lerp 更改transform.rotation。其余代码保持不变。有关该解决方案,请参阅我的 other 答案。 Unity 线程并没有那么过分,因为 Unity 必须支持 20 种不同的平台,并提供一些合理的行为保证。鉴于此,他们在 IMO 方面做得很好。【参考方案2】:

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;
    

【讨论】:

这个确实很好用,大家应该学会使用InvokeRepeating。通常,在这里使用协程是惯用的。【参考方案3】:

您可以使用协同程序来执行此操作。为此,请创建一个返回类型 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,因为他们在解释这一点方面做得比我在这里做得好得多

【讨论】:

以上是关于随着时间的推移移动游戏对象的主要内容,如果未能解决你的问题,请参考以下文章

随着时间的推移旋转游戏对象

仅在相机视图前生成敌人游戏对象,同时相机随玩家游戏对象移动

unity摄像头怎么随着游戏对象移动

swift spritekit 随着游戏时间的推移增加重力?

IOS - 如何应用恒定速度 - Swift 3

随着时间的推移平滑值:移动平均线还是更好的东西?