This document is about: FUSION 2
SWITCH TO

Tanknarok

Level 4

概述

Fusion Tanknarok 範例展示了如何組建一個小型多人競技場風格坦克遊戲,該遊戲在Hosted Mode下運行,具有權威伺服器(可以是獨立應用程式或同時運行伺服器和客戶端的單個應用程式),也可以在Shared Mode下運行,其中每個客戶端都對自己的物件擁有授權,而有一個客戶端控制「共享」物件。

這個例子中的遊戲可能在Steam中看起來很熟悉,因為遊戲邏輯、音訊和精彩的圖形都是由我們在Polyblock Studios的朋友提供的。這個範例只是移植到Photon Fusion的實際遊戲的一小部分;最初的遊戲是用Photon Bolt製作的。

Fusion Tanknarok範例展示了如何在沒有將預測網路系統與非確定性剛體物理引擎(如PhysX)混合所導致的複雜性的情況下,實現類似物理的效果;Fusion完全支援同步Unity剛體,如果需要的話。

在您開始之前

使用3D範本建立一個新的Unity專案,確保在Project Settings > Player > Other Settings > Color Space中將顏色空間設定為「線性」

在下載和匯入範例之前,請確保專案中包含Unity後處理套件。

  1. 導航到Window > Package Manager
  2. 選擇Packages: Unity Registry
  3. 搜尋「後處理」;及,
  4. 安裝套件。

畫面截圖

下載

版本 發佈日期 下載
2.0.1 Jun 10, 2024 Fusion Tanknarok 2.0.1 Build 569

聚焦點

  • 共享及主機端模式支援
  • 延遲補償的射線投射
  • 預測性生成
  • 物件輪詢
  • 完整遊戲迴圈

專案

在運行展示案例之前,必須建立Photon Cloud的 Fusion 應用程式帳號,並將其複製貼上到PhotonAppSettings資產中。可以從Photon儀表板建立應用程式帳號。確保建立一個 Fusion 應用程式帳號,而不僅僅是一個Realtime帳號。

可從Fusion選單Fusion > Realtime Settings選擇Photon應用程式設定資產

只需將生成的應用程式帳號貼上到App Id Fusion欄位中。

資料夾架構

Tanknarok衍生範例的程式碼位於/Scripts資料夾中,其中一個Utility子資料夾用於通用目的公用程式,另一個FusionHelpers資料夾用於非特定於本例子的Fusion公用程式。

剩下的Tanknarok資料夾包含實際的遊戲程式碼,分為以下子資料夾:

  • 音訊 - 音效和音樂
  • 相機 - 相機放置程式碼
  • 關卡 - 所有關卡的邏輯和行為、強化物和其他非玩家物品
  • 玩家 - 所有坦克控制、武器和子彈邏輯以及坦克視覺代表和效果
  • UI - 使用者介面元件

在主資料夾中,主要入口點是GameLauncher類別和頂層關卡管理器GameManagerLevelManagerPlayerManager

Tank Game
坦克遊戲選單。

快速Fusion入門

Fusion透過NetworkObject元件識別網路狀態;任何具有已連網狀態的遊戲物件上都必須有一個NetworkObjectNetworkObject本身只是為遊戲物件指派一個網路內的標識,實際的網路狀態儲存在從NetworkBehaviour衍生的元件中。Fusion有幾個預設行為,例如NetworkTransform,它同步Unity轉換。

類似於FixedUpdate()中物理行為如何轉換物理狀態,NetworkBehaviourFixedUpdateNetwork()方法中轉換其網路狀態。這與轉譯幀率無關,也與網路更新無關,而以固定的時間步長(稱為刷新)進行。每次更新都會簡單地消除上一次刷新的狀態。當網路確認給定刷新的狀態時,Fusion將把物件狀態回復到該刷新,並將所有中間調用重新應用到在那時和當前刷新之間的FixedUpdateNetwork()

由於當前本機刷新總是在最後一個確認刷新的之前,因此更新被稱為「預測」,驗證狀態的應用和隨後重新執行FixedUpdateNetwork方法被稱為「復原」和「重新模擬」。

元件可以在沒有任何網路狀態的情況下成為模擬的一部分,但它應該從SimulationBehaviour而不是NetworkBehaviour衍生,以減少額外負荷。請注意,由於重新模擬,FixedUpdateNetwork()方法在每幀中可能被調用多次-這在專門處理網路狀態時不是問題,因為它會被重置,但 在將差量更改應用於非連網狀態時要小心

有關模擬、預測和網路物件的更多資訊,請參閱Fusion操作手冊。

遊戲啟動器

坦克遊戲的主UI由GameLauncher類別處理。

一旦選擇了遊戲模式,遊戲啟動器將調用FusionLauncher.Launch()以建立遊戲階段。FusionLauncher將回應Fusion連線事件並調用提供的回調,以生成初始網路物件:

  • 遊戲管理器(由主機在主機端模式下生成,或由主客戶端在共享模式下生成)
  • 玩家(由主機在主機端模式下生成,或由各自的客戶端在共享模式下生成)

準備好

當玩家連線時,玩家的坦克會立即生成,並且在「大廳」模式下完全可控制,在那裡他們可以在等待剩餘坦克生成的同時四處遊玩。

直到所有連線玩家都表示他們已經準備好了,遊戲才會開始。此邏輯在所有客戶端上運行,但只有具有GameManager執行個體的StateAuthority的客戶端才能載入該關卡。

注意事項: 在這個簡化的例子中,關卡與其說是「載入的」,不如說是「啟用的」,因為這兩個關卡從一開始就在初始場景中。

載入是透過遠端程序調用完成的。調用方生成隨機關卡索引並將其傳送到所有客戶端,確保每個客戶端都載入相同的關卡。

C#

    if (Object.HasStateAuthority) {
        RPC_ScoreAndLoad(-1,0, _levelManager.GetRandomLevelIndex());
    }

RPC本身被定義為

C#

    [Rpc(sources: RpcSources.StateAuthority, targets: RpcTargets.All, InvokeLocal = true, Channel = RpcChannel.Reliable)]
    private void RPC_ScoreAndLoad(int winningPlayerIndex, byte winningPlayerScore, int nextLevelIndex)
    {
        ...
    }
Tank Game
等待玩家準備好。

關卡過渡

從大廳到關卡(反之亦然)的過渡由TransitionSequence()協同常式中的LevelManager處理。過渡本身完全在本機時間運行,但當它被觸發時(透過RPC_ScoreAndLoad遠端程序調用)以及當它終止時(透過將playState設定為LEVEL,因為這是一個只能由GameManager狀態授權設定的已連網屬性),它會在客戶端之間同步。

在遊戲結束時,關卡過渡將返回大廳,並以大致相同的方式顯示獲勝者,完成迴圈並將遊戲返回到準備狀態。

Tank Game

處理輸入

Fusion使用Unity的標準輸入處理機制來捕捉玩家輸入,將其儲存在可以透過網路發送的資料結構中,然後在FixedUpdateNetwork()方法中處理該資料結構。在本例子中,所有這些都是由InputController類別執行的,儘管它將實際狀態更改交給Player類別。

射擊

本例子中的坦克有4種不同的武器,具有兩種不同類型的命中檢測:

  • 即時命中
  • 拋射物

分別由HitScanBullet類別執行。兩者都使用了物件輪詢、預測生成和延遲補償這三個重要的Fusion功能。

Weapons
拋出炸彈。

物件池

為了避免在生成新物件時掉幀,建議重用舊物件,而不是一直破壞和具現化新物件。這適用於任何遊戲,尤其是Unity,甚至是Fusion。

為了方便這一點,Fusion允許應用程式指定一個鉤來提供和收集回收的遊戲物件。

物件池必須執行NetworkObjectPool,它基本上有一個方法,該方法基於預製件從池中獲取物件,另一個方法將物件返回到池中以供重用。

預測生成

預測生成允許客戶端預測新已連網物件的建立,建立一個臨時本機預留位置,直到狀態授權確認建立。一旦確認,Fusion將自動將預留位置提升為實際的已連網物件。

需要手動處理的是 已失敗 的預測。 這可以簡單到破壞預留位置(記住,它只是一個Unity物件);該應用程式可以自由執行各種形式的淡出或失敗視覺效果。

此外,由於預留位置沒有狀態,應用程式將需要在已預測階段以不涉及存取任何已連網屬性的方式管理移動。

延遲補償

在本機,每個玩家都會看到他們自己的(輸入授權)物件的已預測未來版本,以及其他客戶端物件的內部或外部極化版本;兩者都與伺服器所看到的內容不完全一致。因此,快速移動的物件,例如子彈,很可能會擊中各個機器上的不同物體。如果有什麼問題,開槍的人是最有可能注意到的人。然而,與此同時,伺服器應該有權進行命中偵測,以避免客戶端簡單地認為他們成功命中。

為了解決這個問題,Fusion支援延遲補償射線投射。這些基本上是射線投射,即使在伺服器上運行,也會尊重客戶端在設計時看到的內容。顯然,在幕後有很多快照內插補點的魔力在發揮作用;幸運的是,對於開發人員來說,執行和使用延遲補償射線投射與使用常規Unity射線投射一樣簡單。

唯一需要知道的是,它有自己類型的碰撞器物件,稱為HitBoxHitBox應該是物件層次結構中完全包含的HitBoxRoot節點的同層或下層。這允許Fusion在對下層節點執行更昂貴的檢查之前快速消除根。

出於效能原因,不應將HitBox應用於靜態實體。不過,仍然需要靜態環境來阻擋靜態投射,因此延遲補償的射線投射也可以選擇性地檢查Unity碰撞器。

需要注意的是,延遲補償不適用於動態(即移動)PhysX碰撞器;此外,Unity沒有提供區分靜態和動態碰撞器的射線投射査詢。因此,為了篩選PhysX碰撞器並僅具有靜態結果,建議在動態物件的不同層上具有HitBox/HitBoxRoot和PhysXCollider(如果兩者都需要)。

Weapons
為了獲勝。
Back to top