簡體   English   中英

統一 2D 的物理運動

[英]Physics movement for unity 2D

我有一個 XY 位置的球員。 對於 x 區域,玩家的滑動位置必須在 1 上增加或減少。 試圖通過addForcevelocity來做到這一點,但這些方法正在將 x-area pos 增加到無窮大。 那么 - 在(0,0)之后,我如何停止增加位置(1,0)? 或 mb 有什么其他方法可以幫助我嗎?

    void FixedUpdate()
    {
        if (Input.touchCount > 0)
        {
            theTouch = Input.GetTouch(0);

            if (theTouch.phase == TouchPhase.Began)
            {
                theTouchStartPos = theTouch.position;   
            }

            if (theTouch.phase == TouchPhase.Ended)
            {
                theTouchEndPos = theTouch.position;     

                if (theTouchEndPos.x <= theTouchStartPos.x)
                {
                    Debug.Log("swipe left");
                    Move(Vector2.left);
                }

                if (theTouchEndPos.x >= theTouchStartPos.x)
                {
                    Debug.Log("swipe right");
                    Move(Vector2.right);
                }
            }
        }
    }

    void Move(Vector2 direction)
    {
        //playerRb.velocity = new Vector2(direction.x, direction.y) * speed;
        float step = speed * Time.deltaTime;
        playerPos = Vector2.Lerp(playerPos, playerPos + direction, step);
    }

不要在FixedUpdate()采用單幀輸入,例如TouchPhase.BeganGetKeyDown 它可能適用於您的機器,但不會每次都在更快的機器上注冊輸入。

“FixedUpdate 通常比 Update 更頻繁地調用。如果幀速率低,它可以每幀調用多次,如果幀速率高,則可能根本不會在幀之間調用它。” - https://docs.unity3d.com/Manual/ExecutionOrder.html

這意味着當您按下時,不能保證FixedUpdate在幀上運行,因此如果幀速率足夠高,則僅持續一幀的輸入(例如TouchPhase.BeganGetKeyDown可能不會注冊。

令我驚訝的是沒有其他人注意到這一點。

所以聽起來您想要實現的是:每次滑動都會使您的播放器在 X 軸上向左或向右移動一個“步”,但要平穩。

在您當前的方法中,當觸摸結束時,您僅在一幀內調用Lerp ,因此對象幾乎不會移動。

我寧願設置目標 x 軸位置,並讓玩家在每次物理更新調用中以給定的速度向其移動。

正如SpicyCatGames正確指出的那樣,您應該始終將用戶輸入 ( Update ) 的處理與物理 ( FixedUpdate ) FixedUpdate

private float targetX;

private void Awake ()
{
    targetX = playerRb.position.x;
}

void FixedUpdate()
{
    // Move the player towards the target position but only on X
    // -> keep the Y velocity
    var position = playerRb.position;
    position.x = Mathf.MoveTowards(position.x, targetX, speed * Time.deltaTime);
    playerRb.MovePosition(position);
}

private void Update ()
{        
    if (Input.touchCount > 0)
    {
        theTouch = Input.GetTouch(0);

        if (theTouch.phase == TouchPhase.Began)
        {
            theTouchStartPos = theTouch.position;   
        }
        else if (theTouch.phase == TouchPhase.Ended)
        {
            theTouchEndPos = theTouch.position;     

            if (theTouchEndPos.x < theTouchStartPos.x)
            {
                Debug.Log("swipe left");
                Move(-1);
            }
            else if (theTouchEndPos.x > theTouchStartPos.x)
            {
                Debug.Log("swipe right");
                Move(1);
            }
        }
    }
}

void Move(float direction)
{
    targetX += direction;
}

這似乎得到了很多討論。

FixedUpdate用於物理“計算”

如果你正在制作動畫——也就是說,你想在每次繪制場景時繪制一些東西(可能改變位置)——你會經常使用 Update,而不是 FixedUpdate。

在 FixedUpdate 調用上更改對象的位置既沒有意義(也不准確)。

假設這代表時間,F 是固定更新事件,D(平局)是更新事件

F  F  F    F F  F F  F  F   F  F  F  F F  F F  F 
 D       D           D  D       D         D

您(當然,顯然)只需要在要繪制對象時設置對象的位置。

事實上,當你要繪制它時:你(顯然)想要它在那個實際時間應該處於的位置。

(此處給出的腳本顯示“F”和“D”正在運行 .. https://docs.unity3d.com/ScriptReference/MonoBehaviour.FixedUpdate.html

正如文檔中所解釋的,FixedUpdate 用於物理>>計算<<。 因此,如果您要擴展物理引擎、模擬某些東西、應用子彈游戲的精確規則,或者其他什么。 (我很少使用它。)請注意,有趣的是,如果由於某種原因你正在計算一個行星或其他東西並且在每次 FixedUpdate 時都這樣做,你仍然需要實際設置行星的位置(或任何它是) 在您即將繪制它的確切時刻! (即在更新中。)


這是著名的 Unity doco 的另一個很好的例子。 在許多地方,它們顯示某些東西正在移動(即,使用更新,當平局發生時)。 在那個 FixedUpdate 頁面上,它非常令人困惑地只是提到了非常模糊的物理“計算”。 如果他們再添加幾個詞(“對於幕后物理計算,您實際上並沒有獲得繪制即將繪制的東西的位置”) ,一切都會更清楚!

暫無
暫無

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

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