當(dāng)前位置: 首頁 > 資訊動(dòng)態(tài) > 企業(yè)動(dòng)態(tài)
在 FPS 游戲里,一個(gè)角色被擊殺之后,往往會(huì)以敵方的視角回放本角色被定位、瞄準(zhǔn)、射擊的過程,這就是咱們常提到的死亡回放(DeathCameraReplay)。相似的,咱們?cè)诟鞣N體育游戲外面常常須要在一次得分后展現(xiàn)精彩霎時(shí),這種性能個(gè)別稱為精彩鏡頭。
上一節(jié)案例應(yīng)用的是基于本地文件存儲(chǔ)的回放零碎,每次播放時(shí)都須要從新加載地圖。那有沒有方法實(shí)現(xiàn)相似實(shí)況足球的實(shí)時(shí)精彩回放呢?有的,那就是基于 DuplicatedLevelCollection 和內(nèi)存數(shù)據(jù)流的回放計(jì)劃。
思考一下,通常射擊游戲里的擊殺鏡頭、體育競技里的精彩時(shí)刻對(duì)回放的根本需要是什么?這類回放性能往往是在某個(gè)工夫點(diǎn)能夠無感知地立即切換到回放鏡頭,并在回放完結(jié)后迅速再切換到失常的游戲環(huán)境。同時(shí),思考到聯(lián)機(jī)的狀況,咱們?cè)诨胤艜r(shí)要放棄游戲世界的失常運(yùn)行,從而確保不錯(cuò)過任何服務(wù)器的同步信息,不影響其余玩家。
為了實(shí)現(xiàn)上述的要求,咱們須要將回放的場景和實(shí)在的場景進(jìn)行拆散,在不從新加載地圖的狀況下疾速地進(jìn)行切換??栈靡娼o出的計(jì)劃是對(duì)游戲世界 World 進(jìn)行進(jìn)一步的拆分,把所有的 Level 組織到了三個(gè) LevelCollection 外面,別離是:
要留神的是,因?yàn)?LevelCollection 的引入,原來很多邏輯都變得復(fù)雜了。
思考到在死亡回放的時(shí)候不會(huì)影響失常較量的進(jìn)行和錄制,所以咱們通常也須要講錄制邏輯與播放邏輯齊全拆散。
簡略來說,就是創(chuàng)立兩個(gè)不同的 Demonetdriver,一個(gè)用于回放的錄制,另一個(gè)用于回放的播放。在游戲一開始的時(shí)候,就創(chuàng)立一個(gè) DemonetdriverA 來開始錄制游戲,當(dāng)角色死亡觸發(fā)回放的時(shí)候,這時(shí)候創(chuàng)立一個(gè)新的 DemonetdriverB 來進(jìn)行回放數(shù)據(jù)的讀取并播放,整個(gè)過程中 DemonetdriverA 始終在處于錄制狀態(tài),不會(huì)受到任何影響。(須要咱們手動(dòng)重寫 GameInstance::PlayReplay 函數(shù),因?yàn)槟J(rèn)的邏輯每次創(chuàng)立一個(gè)新的 Demonetdriver 就會(huì)刪掉原來的那個(gè)。)
當(dāng)然,想要實(shí)現(xiàn)真正的疾速切換,只將回放場景與真實(shí)世界的拆散還不夠,咱們還須要保障回放數(shù)據(jù)的加載也能達(dá)到毫秒級(jí)別。所以這個(gè)時(shí)候就不能再應(yīng)用后面提到的 LocalFileNetworkReplayStreamer 把數(shù)據(jù)放到磁盤上,正確的計(jì)劃是采納基于內(nèi)存數(shù)據(jù)流的 ReplayStreamer 來放慢回放數(shù)據(jù)的讀取。上面是 InMemoryNetworkReplayStreamer 對(duì)回放數(shù)據(jù)的組織形式,每幀的數(shù)據(jù)流會(huì)依據(jù)工夫分段存儲(chǔ)在 StreamChunks 外面,而不同工夫點(diǎn)的快照則會(huì)存儲(chǔ)在 Checkpoints 數(shù)組外面。對(duì)于射擊游戲,咱們通常會(huì)在較量一開始就執(zhí)行錄制,錄制的數(shù)據(jù)會(huì)一直寫到上面的構(gòu)造外面并在整場較量中始終保留著,當(dāng)玩家被擊殺后就能夠立即從這里取出數(shù)據(jù)來進(jìn)行回放。
對(duì)于死亡回放 / 精彩鏡頭其實(shí)還有很多細(xì)節(jié)問題,這里列舉一些(最初一節(jié)會(huì)給出一些倡議):
引擎編輯器外面默認(rèn)不反對(duì) DynamicDuplicatedLevels 的創(chuàng)立,所以在不改源碼的狀況下無奈在編輯器外面實(shí)現(xiàn)死亡回放性能。
回放世界與真實(shí)世界都是存在的,能夠通過 SetVisible 來解決渲染,然而回放世界的物理怎么管制?
回放世界默認(rèn)狀況下不會(huì)復(fù)制 Controller(容易和本地的 Controller 發(fā)生沖突),所以很多相干的接口都不能應(yīng)用。
因?yàn)椴煌?Collection 的 Tick 更新機(jī)會(huì)不同,然而 Controller 只有一個(gè),所以回放的時(shí)候要留神 Controller 的更新機(jī)會(huì)。
在 CSGO、Dota、堡壘之夜等游戲里,都反對(duì)玩家觀戰(zhàn)的性能,即玩家能夠通過客戶端間接進(jìn)入到某個(gè)正在進(jìn)行的較量的場景里進(jìn)行實(shí)時(shí)觀戰(zhàn)。不過個(gè)別狀況下并不是嚴(yán)格意義上的齊全實(shí)時(shí),通常依據(jù)狀況會(huì)有肯定水平的提早。
實(shí)現(xiàn)該性能的一個(gè)繁難計(jì)劃就是讓觀戰(zhàn)的玩家作為一個(gè)客戶端連貫進(jìn)去,而后實(shí)時(shí)地承受服務(wù)器同步數(shù)據(jù)來進(jìn)行觀戰(zhàn)。這種形式既簡略,成果也好,然而問題也十分致命——觀戰(zhàn)的玩家可能會(huì)影響失常服務(wù)器性能,無奈很好地反對(duì)大量的玩家進(jìn)入。
所以大部分的游戲?qū)崿F(xiàn)的都是另一種計(jì)劃,即基于 Webserver 和回放的觀戰(zhàn)零碎。這種計(jì)劃的思路如下圖,首先咱們須要專門搭建一個(gè)用于解決回放數(shù)據(jù)的 WebServer,源源不斷地接管來自 GameServer 的回放錄制數(shù)據(jù)。而后客戶端在申請(qǐng)觀戰(zhàn)時(shí)不會(huì)去連貫 GameServer,而是間接通過 Http 申請(qǐng)以后須要播放的回放數(shù)據(jù),從 WebServer 拿到數(shù)據(jù)后再進(jìn)行本地的解析與播放。盡管會(huì)有肯定的提早,然而現(xiàn)實(shí)狀況下成果和間接連入戰(zhàn)斗服觀戰(zhàn)是一樣的。
后面咱們提到過基于 Httpstream 的數(shù)據(jù)流,正是為這種計(jì)劃而實(shí)現(xiàn)的。去認(rèn)真看一下 FHttpNetworkReplayStreamer 的接口實(shí)現(xiàn),都是通過 Http 協(xié)定對(duì)回放數(shù)據(jù)進(jìn)行封裝而后通過固定的格局來發(fā)給 WebServer 的(格局能夠依照需要批改,和 WebServer 的代碼要當(dāng)時(shí)規(guī)定對(duì)立)。
后面咱們花了大量的篇幅,由淺入深地解說了回放零碎的概念以及原理,而后又對(duì)兩個(gè)具體的實(shí)際案例(死亡回放、觀戰(zhàn)零碎)做了進(jìn)一步的剖析,心愿這樣能夠幫忙大家更好地了解 UE 乃至其余游戲外面回放零碎的思維思路。
這是侑虎科技第 1367 篇文章,感激作者 Jerish 供稿。歡送轉(zhuǎn)發(fā)分享,未經(jīng)作者受權(quán)請(qǐng)勿轉(zhuǎn)載。如果您有任何獨(dú)到的見解或者發(fā)現(xiàn)也歡送分割咱們,一起探討。(QQ 群:465082844)
【USparkle 專欄】如果你深懷絕技,愛“搞點(diǎn)鉆研”,樂于分享也博采眾長,咱們期待你的退出,讓智慧的火花碰撞交錯(cuò),讓常識(shí)的傳遞生生不息!
本站部分資源來自于網(wǎng)絡(luò)收集,若侵犯了你的隱私或版權(quán),請(qǐng)及時(shí)聯(lián)系我們刪除有關(guān)信息。聯(lián)系郵箱:九游娛樂中心