簡體   English   中英

Unity線性插值平滑3D運動

[英]Unity linear Interpolation for smooth 3D movement

所以我正在嘗試創建一個向前運行的游戲(類似於 Temple Run),但我希望我的角色能夠順利地左右移動,而不僅僅是傳送。 我嘗試使用Vector3.Lerp()但我無法理解它是如何工作的。

這是我嘗試過的,但角色只是瞬移

    void Update()
    {
        if(Input.GetKeyDown("a")&&lane-1>0)
        {
            lane-=1;
            shouldMove = true;
            Vector3 newpos= new Vector3(transform.position.x -2.5f, transform.position.y, transform.position.z);
            while (shouldMove)
            {
                transform.position = Vector3.Lerp(transform.position, newpos, 0.1f * Time.deltaTime);
                if(transform.position.x>=newpos.x)
                {
                    shouldMove = false;
                    transform.position = newpos;
                }
            }

此示例僅用於向左移動。

您認為使用Vector3.Lerp在開始值和結束值之間逐漸插值是正確的。 但是,實現和用例並不完全適合您嘗試做的事情。

由於您僅更改運動的單個軸,因此我不會使用Vector3.Lerp ,而是使用Mathf.Lerp因為您僅更改 position 的 x 軸。

您使用的是while循環而不是Update ,這意味着程序將停留在該循環內,直到該過程完成。 它立即移動到下一點的原因是由於您的if條件。 您從當前值中減去2.5 ,然后不斷檢查當前 position x 是否大於新值,這始終是正確的。 它會立即將您當前的 position 設置為您的新 position,然后跳出您的 while 循環。 另一個問題是您正在使用GetKeyDown ,它只發生在用戶單擊鍵的一幀。 Lerps意味着隨着時間的推移完成,而不是立即完成。

與其將您的邏輯放在Update中,我會考慮將實際運動移至稱為 Coroutine 的特殊Coroutine Courtines想象為一個在多個幀上完成的過程,然后跳回到上一幀中斷的地方。 Coroutines非常強大,但請在過度使用它們之前仔細閱讀文檔,以深入了解它們的作用。

現在進行實施。 我不完全確定你的車道設置,但會假設你有 3 條車道,類似於其他無限跑道游戲。 我會將輸入檢測保留在Update內部,並允許玩家從中間從一側跳到另一側,但不會偏離軌道,也不會在跳躍時跳躍。 我還將使用時間而不是速度來控制Lerp的跳躍,如果您願意,您可以輕松地將其更改為速度。

[SerializeField] private float TimeForJump = 0.25f;
[SerializeField] private float JumpOffset = 2.5f;

// I am assuming your setup for lanes is -1 | 0 | 1
private int lane = 0;
private Coroutine PlayerJumping = null;

void Update()
{
    // no need to detect input if we are already jumping
    if(PlayerJumping == null)
    {
        // instead of 'a' and 'd' you can use GetAxis to allow for arrow key and wasd support
        // it is also an easy way to determine direction when adding or subtracting for a goal location
        float horzInput = Input.GetAxis("Horizontal");

        if (horzInput < 0 && lane > -1)
        {
            PlayerJumping = StartCoroutine(Jump(-1));
            lane--;
        }
        else if(horzInput > 0 && lane < 1)
        {
            PlayerJumping = StartCoroutine(Jump(1));
            lane++;
        }
    }

    // simulating your movement
    transform.position = new Vector3(transform.position.x, transform.position.y + 0.1f, transform.position.z);
}

/// <summary>
/// Horizontally have the player jump
/// </summary>
private IEnumerator Jump(float direction)
{
    // store our current position
    float currentXPos = transform.position.x;

    // our goal position
    float goalXPos = currentXPos + (direction * JumpOffset);

    // timer for how long it has passed since we started the jump
    float jumpTimer = 0.0f;

    // continue the lerp for the time we have left
    while(jumpTimer <= TimeForJump)
    {
        transform.position = new Vector3(Mathf.Lerp(currentXPos, goalXPos, jumpTimer / TimeForJump), transform.position.y, transform.position.z);

        // increment the time that has passed
        jumpTimer += Time.deltaTime;
        yield return null;
    }

    // set our position directly in case of floating point errors
    transform.position = new Vector3(goalXPos, transform.position.y, transform.position.z);

    // set the coroutine to null so we can jump again
    PlayerJumping = null;
}

由於我不確定你的實現是如何完成的,所以我對車道和其他一般設置有一些假設。 答案非常通用,因此可以根據您的需要進行調整。 如果您願意,您也可以將輸入交換回GetKeyDown ,我使用它的唯一原因是您可以獲得箭頭鍵和 wasd 輸入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM