中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

理解Unity的Timesteps(步長)和實現平滑移動

發布時間:2020-02-29 07:38:34 來源:網絡 閱讀:21966 作者:xiaosongfang 欄目:游戲開發

首先不知道有沒有像我一樣,一直不是很清楚Timesteps具體怎么解釋的,稍微找了一下:

理解Unity的Timesteps(步長)和實現平滑移動


上面說的是兩個物理檢測幀之間的時間間隔

如果不是物理的話,可以直接理解為,兩幀之間的時間間隔


-----



接下來開始翻譯原文

原文:http://www.kinematicsoup.com/news/2016/8/9/rrypp5tkubynjwxhxjzd42s3o034o8


在Unity社區里,其中有一個辯論的最為激勵的話題,就是何如去除游戲中生澀的動作,讓它顯得自然。這個問題不只是在Unity引擎才有,所有引擎都有這個問題,而且他的產生的原因來自于你的引擎用怎么樣的timesteps。

并沒有哪種解決方案能解決所有的這些情況,不過有一種直接的方法解決問題。許多開發者遇到這個問題是在移動的過程中,發現物體一抖一抖的,而且想要改善很難。令人驚訝的是,外面關于unity的timesteps有很多誤傳,許多unity論壇的回答者,即使他說對了,也沒有綜合的分析,并且留下了許多理解上的空白讓人無法完全解決這些問題。本文旨在在更深層次的解釋unity的timesteps來解決這個問題,解釋為什么會產生抖動,并提供一個解決方案來解決這個問題。并且發布了一個AssetPackage來演示這個解決方案

理解Unity的Timesteps(步長)和實現平滑移動

額!這種類型的抖動是不是很熟悉?


上面的這個圖片就是一種簡單的運動抖動。很明顯這并不是我們想要出現在游戲里的畫面。如果你要重現這個非常簡單:

  1. 創建一個新project

  2. 導入一個默認的第一人稱角色控制器,放在一個新場景

  3. 放置一些物件,并選擇一個朝著它畫圓

刪除掉頭的擺動,放置一個游戲平板在地面使得觀察效果更佳明顯。一般情況下,你能注意到,當你繞著它轉時,這里會有特別明顯的抖動。

現在看看這種情況,當我使用了稍后會討論的這些技術。和第一個例子對比,你能明顯看到在順滑上的重要的變化。

理解Unity的Timesteps(步長)和實現平滑移動

 如絲般順滑,好多了!

在解決這個問題之前,先去理解Unity(Mono)的生命周期是很重要的。特別是,我們必須去探索Update和FixedUpdate背后的邏輯。下面的鏈接是一遍來自Unity官方文檔的,關于Unity生命周期的小的摘錄:

https://docs.unity3d.com/Manual/ExecutionOrder.html

特別提醒一下,如果你以前沒有注意過Update的執行順序,那么你需要特別的研究一下,因為接下來的部分與這個密切相關。

理解Unity的Timesteps(步長)和實現平滑移動

Unity的各個Update的執行順序,原文:https://docs.unity3d.com/Manual/ExecutionOrder.html

先了解這個流程圖(生命周期)。


這個流程圖概括了Unity的各個Update執行順序中,一幀里面哪些函數會被調用。這部分我們需要注意的是FixedUpdate和Update函數,圖上綠色和紅色的部分。

Unity實現的是半固定的timestep。這意味著主游戲循環用一個可變的timestep跑在任何幀率上,這個在Unity里叫做deltaTime。并且用來控制一個使用固定timesteps的內部的循環。

這里有一些好處:

首先,在游戲中物理在固定幀率的檢測下,可以進行游戲中畫面上的高幀率的Update,只要硬件允許。

相反的,這里也有一些壞處,容易出現上面所說的抖動。

下面是簡單的用代碼來解釋一下Unity的Update循環的結構:

float currentSimulationTime = 0;
float lastUpdateTime = 0;

while (!quit) // variable steps
{
        while (currentSimulationTime  < Time.time) // fixed steps
        {		
              FixedUpdate();
              Physics.SimulationStep(currentState, Time.fixedDeltaTime);
              currentSimulationTime += Time.fixedDeltaTime;
        }
 Time.deltaTime = Time.time - lastUpdateTime;
 Update();
 Render();
 lastUpdateTime = Time.time;
}

這個Update函數對你來說應該很熟悉了,它在Monobehaviours的每幀里,在輸入已經執行后,在渲染前的中間這段時間里被調用。

如果垂直同步關閉了的話,當一幀結束以后,Unity會立刻執行下一幀,這樣子去獲得盡可能高的幀率。

當每幀的硬件和計算量在不停的變化時,幀率也會不停的變化,即使垂直同步打開了,由于Unity嘗試去讓每個幀率盡量相同,也不會真的固定不變。

由于以上這些,Update函數能在一秒內被調用任意次數。


FixedUpdate在每次Monobehaviors的物理檢測中進行。即使多個物理檢測中,他們的檢測的時間間隔不是相同的時間,Unity也會把他們放到固定的時間間隔內調用。 這是因為在游戲的物理里,尤其是加速運動中,使用固定的時間差,是最準確和最穩定的。在Unity里,這個固定的時間差就叫做fixedDeltaTime。默認的時候,fixedDeltaTime的值為0.02,這意味著在游戲里每秒鐘總有50次FixedUpdate的調用。用這種方法,你可以理解FixedUpdate是一個獨立的幀率,它在每秒鐘被調用的次數是固定的,即使這時你的渲染幀率非常低或者非常高。重點的提出FixedUpdate和物理的循環是相關關聯的很有必要的,不是發現在不同線程的。


基于這點,一起來觀察一下幾個關于更新時機的例子。


理解Unity的Timesteps(步長)和實現平滑移動


上面是當每秒有50個FixedUpdate和60個Update的時候的更新時機。可是,在實際中由于幀率是不固定所以不會這么完美,下面這個圖這個就是現實中的,一點點夸大的時間軸。注意到,有一些Update之間是沒有FixedUpdate的,這種情況一般出現在渲染簡單畫面的時候。另一方面一些Update之間有還幾次FixedUpdate,這個一般出現在加載資源的過程中。這意味著,即使你盡可能的讓Update和FixedUpdate次數相同,這也很難做到對齊。

理解Unity的Timesteps(步長)和實現平滑移動

根據我們對Unity的timesteps的知識,我們可以理解下面的這個案例。這個場景里,一個球和照相機繞著同一個支點。這個球的transform的改變放在Update循環里,與此同時,左邊照相機的transform改變放在FixedUpdate循環里,右邊的照相機放在Update循環里。左邊這個看起來就有很明顯的抖動,右邊的就很順滑

理解Unity的Timesteps(步長)和實現平滑移動

左邊的照相機在FixedUpdate里移動,右邊的在Update里


由于Update和FixedUpdate的調用不在通過頻率上,當球在移動的時候照相機依然還在原地。這就導致了球相對于照相機移動的不同步,產生了抖動。當在慢鏡頭下,這些行為就更為明顯。

理解Unity的Timesteps(步長)和實現平滑移動

和上面一樣的模型,5%的速度

所以,我們能看到導致抖動的緣由是因為移動不同的objects的時候,有的在Update里有的在FixedUpdate里。所以簡單的修復方法就是必須把所有移動transform的地方,要不放在Update里,要不放在FixedUpdate里。


然而,這時事情開始變得棘手了,這個常見的回答會使很多Unity開發者把游戲中的許多游戲內的運動放在Update里,而FixedUpdate只放小部分物理邏輯。雖然這有它的優點,比如簡化了你的操作,但是由于很多原因,它是有問題的。也許最大的問題是讓你的游戲依靠畫面的幀率進行。這就導致了有很多bug和連貫性的行為不一致的問題,打開了這些錯誤大門。此外,它會影響很多決策,包括幾乎所有的實時策略類型。當你需要執行加速度運動時,比如玩家的重力,這也會出現問題。像這些物體就應該使用FixedUpdate,但由于其他的物體使用了Update,所以你會看到很多抖動。(請參考標準assets里面的第一人稱控制器來管著這個問題)

因此,一個常見的且有時是必要的選擇是,把所有的狀態和游戲邏輯放在固定的timestep里像FixedUpdate,嚴格的把畫面和輸入信息放在Update里。

然而,這里面不是只有它自己產生的問題,首先,你可能希望你游戲的物理幀也不同于游戲邏輯幀的節奏出現。這個操作非常簡單,Unity給了你很多操作的空間,允許你自己去選擇和優化。接著,輸入信息只在Update里也會有問題,當兩個FixedUpdate直接出現了多個Update時,只有最后那一個Update里的輸入信息會影響到后面的FixedUpdate。這個特然容易出現在上下按鈕事件,因為它們支隊單一幀有用。這個問題的解決方案是,在下一個FixedUpdate前,把輸入信息用一個input buffer進行緩沖。將此行為集成到您使用的任何輸入控制器中是一種相當無縫的方式來執行此操作,并將緩沖保留在一個位置。

然而,一個更大的問題是,一般來說FixedUpdate的調用會比Update少,所以移動物件的頻率跟不上畫面渲染的頻率,導致雖然畫面是流暢的,但是移動的時候斷斷續續的。

有很多種方法可以借鑒這種問題,比如用差值和推測的方法解決,使得可以平滑的移動。差值,可以很方便的流暢的使物體從一個狀態移動到另一個狀態,很容易使用。不過這會導致有一個fixedDeltaTime的延時。這個延時在大部分游戲內的一般情況下,是能被接受的,即使是射擊游戲的射手也可以使用這種方法獲得平滑的移動。推測,是預測物體的下個狀態會在哪個位置,避免了延時,但是本質是更難做到無縫的滑動并且還帶來了性能的壓力。


理解Unity的Timesteps(步長)和實現平滑移動

攝像頭和球都在FixedUpdate中移動,右邊使用了差值計算

以上是演示差值的另一個比較案例。左邊這個圖,鏡頭和球的transform設置都在FixedUpdate里。右邊也是,不過右邊在FixedUpdate的兩次調用之間用了差值計算是的移動的時候更順滑。注意到兩邊的物件都基本保持了一致性,不過右邊的移動更流暢更少抖動。


所以,怎么在Unity用差值計算呢?我做了一個assetPackage,鏈接在下面:

http://ksblogcontent.s3-website-us-east-1.amazonaws.com/TimeStepBlog/Timesteps.unitypackage


此外,您可以獲取用于創建上述示例的構建:

http://ksblogcontent.s3-website-us-east-1.amazonaws.com/TimeStepBlog/TimestepsBuild.zip


具體就看上面的demo了,后面懶得翻了。。。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

九龙县| 怀仁县| 古田县| 盐池县| 乌拉特后旗| 宁乡县| 澄迈县| 南京市| 宁强县| 安多县| 武穴市| 南溪县| 镇远县| 赤城县| 乳山市| 台北县| 纳雍县| 高雄市| 尚义县| 安图县| 三门县| 彭阳县| 韩城市| 芜湖市| 鹤岗市| 怀集县| 来安县| 娱乐| 上思县| 建始县| 永胜县| 德惠市| 聂拉木县| 仁化县| 霍山县| 长葛市| 邛崃市| 穆棱市| 东乡| 游戏| 杭锦后旗|