【面經】騰訊U3d面試面經 幀同步方向(總)

近期拿到了一個騰訊的offer,記錄一下面試過程。

我找的內推,面試的流程如下:

上傳內推簡歷,接着馬上被HR轉到項目組裏面,一個小時左右面試官電話過來約面,接着電話面,然後去科興面,最後HR面,OFFER到手。

總的來說騰訊的面試流程還是挺簡潔的,聽說有人面了很多很多面,我沒有遇到這種情況,不過最後給offer時間間隔太久了,一週半才確認。

 

兩輪技術面試都是在問幀同步相關的問題,所以就一起寫了,也是對幀同步做一個總結吧。(PS:其實我簡歷很多其他方向也很希望面試官能問到啊...)

由於時間比較久了 所以面試的問題可能不是特別準確。

PS。A並不是我面試的時候說的,因爲並不可能在面試的情況下說出那麼完善的邏輯,而是回來覆盤之後,纔想起來然後整理出來的。

Q:幀同步如何解決不同步的問題?

A:https://blog.csdn.net/nxshow/article/details/88382085

Q:幀同步怎麼做到流暢的戰鬥?

A:

首先,定義一下流暢的戰鬥,流暢的戰鬥並不是代表着遊戲的幀數一定要多高多高,而是說遊戲的幀數在某一個幀數範圍內小規模的變動,例如穩定在30幀這樣。

對於單機遊戲來說,如果要保證穩定在30幀,每一幀的邏輯、渲染等耗時不能高於33MS,所以需要小心的規劃每一個函數的使用,採用分幀執行、算法優化等手段優化卡頓點。

而對於幀同步來說,不僅僅需要完成單機遊戲的優化、還要針對網絡波動進行鍼對的優化。我們知道,網絡傳輸無法保證每一次傳輸的延遲都是一定的,有時候10MS就能完成一次傳輸,有時候1000MS才能完成一次傳輸,那麼客戶端如何保證網絡傳輸不穩定的情況下,邏輯幀的運行還是相對穩定的呢?下面是給到的兩種解決方案。

  1. 收到邏輯幀消息之後,不立即去播放,而是存着,播放使用固定的延遲進行播放,表現上就是玩家每次進行操作的時候,並不是馬上生效的,而是有一小段固定延遲,這樣網絡在我們設置的延遲內波動的話,玩家是感受不出來卡頓的。但是缺點也很明顯,每一個玩家都會有一段延遲。
  2. 另外一個處理方式就是,邏輯和表現進行分離,表現幀由玩家和邏輯幀進行驅動,邏輯幀卡頓並不影響表現幀,表現幀由玩家進行控制播放,一旦收到了新的邏輯幀,立即去做校驗,如果說表現幀的播放軌跡和邏輯幀有出入,立即進行糾正。如果說新的邏輯幀並沒有和表現幀有差異,但是表現幀相對邏輯幀差距很大,例如邏輯幀纔到100幀,表現幀就已經到了200幀,這時候就對輸入進行限制,比如移動速度放慢等操作。等待邏輯幀追上表現幀。對於其他玩家,採用AI預測的方式進行預測,一旦預測結果與新收到的邏輯幀不一致,就立即回退;同時,隨着邏輯幀和表現幀的差距越來越大,相應的減緩預測的效果,最終停止預測。如果說邏輯幀突然來了一大波,應該適當的進行加速播放邏輯幀,儘量去追上表現幀。

Q:幀同步環境下如何做網絡流量優化?

A:網絡流量的優化,實際上就是網絡包大小、數量的優化;首先,儘量去減小發送的數據,合理的規劃每一個byte的作用,數量上儘量去合併同一批發送的數據包,減小由於包頭造成的流量損失。

Q: 如何解決UDP丟包問題?

A:

首先明確一點,丟包問題是不可能解決的,在TCP和UDP下都會存在丟包的情況,那麼爲什麼TCP號稱是可靠的傳輸協議呢?這是由於TCP處理了丟包的情況,而UDP是無連接的,每次發出一個數據包之後就不管了,所以丟包的情況是需要我們自己去處理的。

首先,丟包是不可避免的,但是我們應該儘量去避免代碼邏輯造成的丟包,還有就是完善丟包重傳機制。

代碼邏輯造成的丟包,具體來說,是以下幾點:

  1. 發送端發送的數據堆積導致的丟包,也就是發送緩存被填滿了導致的丟包,處理方式就是,控制發送頻率,避免同時發送過多、過大的數據包。
  2. 數據包過大導致的丟包,internet協議規定的MTU大小爲576,也就是目前最差的路由器支持的最小包大小就是576,如果大於這個數字,路由器就有可能對數據包進行分包,這樣就一個包變成了兩個包,兩個包只要有其中一個包丟掉了,就代表這個數據包丟了,所以我們要嚴格控制數據包的大小,去掉UDP包頭20個字節的大小,我們可用的還有556,我們程序中定義爲512,只要超過這個數字,就會強制進行分包發送,接收方接收到數據包的時候,再進行重組。
  3. 接收端卡頓導致的丟包,接收端運行卡頓,導致數據包到接受端的時候Recv函數並沒有在執行,處理方式就是使用多線程去執行Recv函數,這個線程裏面只處理Recv,然後將接收到的數據緩存起來。

 

但是就算這樣處理了之後,由於網絡問題導致的丟包是沒法解決的,所以我們必然要建立可靠的UDP傳輸。也就是實現丟包重傳機制。

  1. 給每一個包規定一個自增的唯一序號,通過ACK確認雙方發送到了那個數據包。
  2. 合理設置RTO(重傳超時時間),TCP貌似是2*RTO, KCP採用的是1.5*RTO。

然後這裏面試官追問,如果說這個包丟了,你一定要等到確認丟包之後重傳嗎?

答案是不會,格鬥遊戲既然使用了幀同步,就是要求實時性能,所以在重傳機制上,還做了冗餘發送的機制,就是在發送當前幀的時候,把前面幾幀的數據一起合併起來發過去,相當於這幾個消息中,只要收到了其中一個消息,就能流暢的播下去。

Q:如何保證在UDP環境下接收邏輯順序一致性?

A:針對每一個數據包進行編號,後發的數據包如果先到了客戶端,就存着,直到接收到的數據包是順序的,才發生到邏輯層進行順序處理

Q:如何實現幀同步環境下的斷線重連?

A:

因爲UDP是無連接的,所以斷線只能通過上次收到的消息時間超時了多久進行判斷,斷線之後客戶端邏輯幀停止,表現幀停止預測。

重連就比較麻煩了,重連回來之後,將邏輯幀、狀態幀拉回來,服務器一次性將斷線之後的消息發給客戶端,客戶端加速播放。

但是如果斷線時間比較久,重連回來之後,消息數據量非常大,需要播放的幀數很多,有沒有優化方法呢?有的,幀同步因爲邏輯是在客戶端運算的,所以幀同步的作弊也比較容易,我們通常會採用專門的驗證服務器去驗證,這個服務器同樣接收客戶端的操作指令,運行戰鬥邏輯,所以我們斷線時間比較久的話,可以去驗證服取到最新的現場數據,再發送現場數據到最新的邏輯幀給客戶端,即可實現快速重連

Q:怎麼去做戰鬥預測?

A:

Q:在幀同步的環境下怎麼防止作弊的情況?

A:

Q:幀同步和狀態同步的區別?爲什麼我們遊戲要用到幀同步?

A:

幀同步和狀態同步都不是新東西,很早以前就有了,以前由於網絡問題,幀同步只存在於局域網遊戲中。幀同步的邏輯放在客戶端,服務器只管轉發;狀態同步的邏輯放在服務端,客戶端只管表現。由於幀同步邏輯是客戶端計算的,所以幀同步的每一個客戶端都要知道場上的所有信息,才能正確的進行計算。而狀態同步的邏輯都在服務端,所以狀態同步不需要每一個客戶端都知道所有的信息,只需要知道這個客戶端所關心的信息就可以了。

因此狀態同步更適合MMORPG這樣的同步客戶端數量較多,信息較爲複雜的情況;而幀同步更適合MOBA這樣的,客戶端數量固定,更關注實時性的情況。

爲什麼我們遊戲需要用到幀同步?我們遊戲是一個格鬥類型的遊戲,對於打擊感、實時性要求較高,而且參與戰鬥的只有兩個客戶端,戰鬥的場景非常簡單,是一個典型的適合使用幀同步的場景。如果我們使用的是狀態同步,每一個客戶端在同一幀的表現不一致,就非常難調打擊感,那麼對於格鬥遊戲來說,沒有打擊感這個遊戲就沒有了靈魂。還有一點,幀同步的邏輯都在客戶端,所以如果需要新增加戰鬥機制,只需要在客戶端修改就可以了,不需要像狀態同步那樣,服務端增加計算邏輯,客戶端增加表現邏輯。開發上非常簡單,邏輯上也非常清晰。

 

除開幀同步 還少量的問了一些其他問題

Q:ETC壓縮算法原理

A:

Q:大地圖下的地圖加載方式?

A:

Q:MMORPG遊戲中多人、多時裝渲染優化方案?

A:

 

問題不止這些,不過面試時間有點久,有些問題已經忘了,這裏先做一個記錄,後面有空再把回答補上

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章