This document is about: FUSION 2
SWITCH TO

Coming from Fusion 1

新功能

Fusion 2為Fusion帶來了各種新功能和改進,強化了API,同時保持了Fusion的核心原則。以下是最重要的改進的清單:

興趣進入/離開回調

新的IInterestEnterIInterestExit回調已新增到Fusion。當網路物件進入/存在給定玩家的AOI區域時,以及當玩家明確對新增或刪除的物件感興趣時(使用Runner.SetPlayerAlwaysInterested()),就會發射這些事件。在伺服器、主機端和共享模式中,在伺服器上可靠地計算回調。

內插補點目標

使用Fusion 1可能很難正確處理內插補點目標,尤其是在為網路物件設定上層關係時。使用Fusion 2,我們簡化了內插補點。不再有內插補點目標,而是對帶有網路轉換的轉換本身進行內插補點。

網路轉換

NetworkTransform有一些更改。請參見網路轉換

本機空間

NetworkTransform現在將其TRS資料(位置/旋轉/縮放)存儲在本機空間中。這意味著:

  • 下層與巢狀NetworkTransform的資料效率高得多
  • 然而,興趣區域位置對巢狀NetworkObject不再有效。引入了AreaOfInterestOverride來處理這一點,並允許NetworkObject指定另一個NetworkObject位置來確定玩家興趣。

同步縮放

現在可以選擇性地同步轉換的本機縮放。

同步上層

現在可以選擇性地同步NetworkObject的上層。有效的NetworkBehaviour必須存在於上層轉換上,並且NetworkTransform必須位於網路物件的根上。

網路物理

NetworkRigidBodyNetworkPhysicsSimulation已從Fusion DLL中刪除,並替換為Unity物理附加元件,其現時包含在Fusion SDK的主要下載中。可用僅伺服器和完整預測物理的完整功能集,我們計畫新增一個新的僅轉傳模式。

透過源程式碼提供物理附加元件,可以修改/擴展它以滿足您的專案需求。這使得VR遊戲等複雜使用案例在使用物理時具有更大的靈活性。雖然NetworkTransform在Fusion 2中刪除了其內插補點目標要求,但NetworkRigidbody仍具有InterpolationTarget屬性。然而,內插補點目標只在非常特定的使用案例中需要,並且通常可以保留為null(表示將移動剛體轉換以進行內插補點)。

更改偵測

一個新的更改偵測API實際上不僅允許偵測Render中的更改,也允許偵測FixedUpdateNetwork中的更改,以觸發遊戲遊玩邏輯。它更完整、更靈活,同時我們仍研究是否應該提供一個簡化的語法糖,其行為也與舊的OnChanged類似。

刷新準確的共享模式

共享模式現在是刷新準確的。 這帶來了許多改進;

  • 共享模式內插補點現在更快捷、更準確。
  • TickTimer現在在共享模式下有效。
  • 已連網Tick值現在在共享模式中是有意義的。

自訂內插補點

我們新增了一個新的內插補點API來存取資料點。它允許您存取自/到資料緩衝,和Fusion用於內插補點所有網路内容的內插補點Alpha。

延遲補償改進

延遲補償得到改進。不再需要將動畫命中盒放置在轉譯之前,以使其處於正確位置。延遲補償將自動使用來自轉譯的與玩家在螢幕上看到的內容相匹配的正確內插補點動畫位置。此外,延遲補償支援2D使用案例,現在也允許査詢2D物理場景。

升級到Fusion 2

影片

有一個影片教程,介紹了簡單Fusion專案的升級過程。

升級Unity版本

Fusion 2支援Unity 2021.x和更新版本的Unity。對於舊版本Unity上的專案,在嘗試升級Fusion之前,請先升級Unity。

升級SDK

  1. 在升級專案之前,請確保使用版本控制系統軟體或等效方法來備份專案。
  2. Assets/Photon/Fusion/Resources/NetworkProjectConfigAssets/NetworkProjectConfig移動NetworkProjectConfig來備份它。
  3. 從專案中刪除/Photon資料夾。
  4. 下載Fusion 2 SDK並匯入Unity套件。
  5. NetworkProjectConfig移回Assets/Photon/Fusion/Resources/NetworkProjectConfig
  6. Fusion 2需要一個與Fusion 1專案不同的應用程式帳號才能工作。在這裡建立一個新的應用程式帳號,並在建立時選擇Fusion 2。在Unity中的Fusion > Fusion Hub下插入新的應用程式帳號。
  7. 開啟/Packages/manifest.json並將現有的可定址套件替換為"com.unity.addressables": "1.21.12"(如果未安裝可定址,則新增新的)。儲存檔案。

匯入套件後,主控台中會出現許多錯誤。這些需要透過升級API來手動修正。

API更改

簡單API更改

先前API 新的API
(整數)玩家參照 PlayerRef.PlayerId
PlayerRef.IsValid PlayerRef.IsRealPlayer
(整數)場景參照 SceneRef.FromIndex
NetworkObject.NetworkGuid NetworkObject.NetworkTypeId
INetworkObjectPool INetworkObjectProvider.
NetworkTransform/NetworkTRSP.TeleportToPosition() NetworkTransform.Teleport()
Runner.Config.DefaultPlayers Runner.Config.Simulation.PlayerCount
[準確度] 移除屬性。沒有替換物。
NetworkRunner.IsVisible NetworkRunner.GetVisible() and SetVisible()
Runner.SimulationConfig.Topology Runner.Topology
NetworkCharacterControllerPrototype NetworkCharacterController
Runner.Simulation.X (Runner.Simulation.Tick) Runner.X (Runner.Tick)
Runner.MultiplePeerUnityScene Runner.SimulationUnityScene
Runner.SetActiveScene Runner.LoadScene(必須只在主機端/主客戶端上調用)

網路物件輪詢

輪詢API發生了重大更改,以允許非同步載入。

INetworkObjectPool已經被重新命名為INetworkObjectProvider

新增了兩個新的更簡單的函數來提供執行個體,可用於輪詢等簡單使用案例:

C#

public class PooledNetworkObjectProvider : NetworkObjectProviderDefault
{
    protected override NetworkObject InstantiatePrefab(NetworkRunner runner, NetworkObject prefab)
    {
        // Get object from pool and return it.
    }

    protected override void DestroyPrefabInstance(NetworkRunner runner, NetworkPrefabId prefabId, NetworkObject instance)
    {
        // Return the instance to the pool.
    }
}

已經調整ReleaseInstanceAcquireInstanceFunctions

C#

public void ReleaseInstance(NetworkRunner runner, NetworkObject no, bool isSceneObject)
{
    ....
}

C#

public void ReleaseInstance(NetworkRunner runner, in NetworkObjectReleaseContext context)
{
    var no = context.Object;
}

AcquireInstance(NetworkRunner runner, NetworkPrefabInfo info)現在是AqcuirePrefabInstance(NetworkRunner runner, in NetworkPrefabAcquireContext context, out NetworkObject result)。傳回參數不再是物件,而是結果(NetworkObjectAcquireResult.Success)。取而代之地透過out參數傳送物件。

內容參數中的IsSceneObject已替換為context.TypeId.IsSceneObject

從:

C#

public NetworkObject AcquireInstance(NetworkRunner runner, NetworkPrefabInfo info)
{
    NetworkObject prefab;
    if (NetworkProjectConfig.Global.PrefabTable.TryGetPrefab(info.Prefab, out prefab))
    {
        var newO = ...
        return newO;
    }
    return null;
}

到:

C#

public NetworkObjectAcquireResult AcquirePrefabInstance(NetworkRunner runner, in NetworkPrefabAcquireContext context, out NetworkObject result)
{
    NetworkObject prefab;
    if (NetworkProjectConfig.Global.PrefabTable.TryGetPrefab(context.PrefabId, out prefab, true) == NetworkPrefabTableGetPrefabResult.Success)
    {
        var newO = ....
        result = newO;
        return NetworkObjectAcquireResult.Success;
    }

    result = null;
    return NetworkObjectAcquireResult.Failed;
}

NetworkProjectConfig.Global.PrefabTable.TryGetPrefab(info.Prefab, out prefab)現在有一個額外的bool IsSynchronous參數(設定為真以保持相同的行為),並傳回NetworkPrefabTableGetPrefabResult列舉而非布林值。

更改偵測

已移除OnChanged。Fusion 2提供了一個新的更泛用的API,其允許在轉譯和固定更新網路中偵測更改。您可以在這裡了解新的更改偵測API的更多資訊。

這裡有一個簡單的例子,將OnChanged替換為等效的基於Render的更改偵測。

從:

C#

public class Example : NetworkBehaviour
{
    [Networked(OnChanged = nameof(OnStateChanged))]
    public int State { get; set; }

    public static void OnStateChanged(Changed<Example> changed)
    {
        var value = changed.Behaviour.State;

        changed.LoadOld;
        var oldValue = changed.Behaviour.State;
    }
}

到:

C#

public class Example : NetworkBehaviour
{
    private ChangeDetector _changes;

    [Networked]
    public int State { get; set; }

    public override void Spawned()
    {
        _changes = GetChangeDetector(ChangeDetector.Source.SimulationState);
    }

    public override void Render()
    {
        foreach (var change in _changes.DetectChanges(this, out var previousBuffer, out var currentBuffer))
        {
            switch (change)
            {
                case nameof(State):
                    var reader = GetPropertyReader<int>(nameof(State));
                    var (previous,current) = reader.Read(previousBuffer, currentBuffer);
                    OnStateChanged(previous, current);
                    break;
            }
        }
    }

    private void OnStateChanged(int oldValue,int value)
    {
    }
}

在更改時轉譯

可以使用單獨的屬性OnChangedRender,而非使用更改偵測器。當偵測到網路屬性發生更改時,這將觸發指派的方法。

這裡是一個示例:

C#

public class Example : NetworkBehaviour
{
    [Networked, OnChangedRender(nameof(OnColorChanged))]
    public Color NetworkedColor  { get; set; }

    public Material material;

    public void OnColorChanged()
    {
        material.color = NetworkedColor;
    }
}

使用OnChangedRender屬性是更改偵測器的更快的替代物,但它的靈活性較小,最好保留給不會對遊戲遊玩產生太大影響的元素。此外,它不支援複製以前的狀態。這可能會導致在生成物件時發生問題,當檢測到更改時,例如更改物件的顏色或顯示的名稱,如果在已生成上未勾選,則可能會遺失這些應該發生的更改。

內插補點目標

內插補點目標不再存在,也不必與NetworkTransform一起使用。自身具有NetworkTransform的物件將相應地在Render中進行內插補點。

已預測生成

已刪除已預測生成,沒有新的APi替換它。不再需要NetworkObjectPredictionKey,從Spawn函數中删除它。

物理

已從Fusion dll中刪除NetworkRigidBodyNetworkPhysicsSimulation。這些已被Unity物理附加元件 IBeforePhysicsStep(及其之後)所取代,並且需要重新映射到RunnerPhysicsSimulate.OnBeforeSimulate(及其之後)

共享模式改進

現在已貼齊刷新。這意味著您可以使用Runner.Tick來參照到共享模式下的特定刷新,並與其他客戶端共享該資訊。這也允許在共享模式下使用TickTimer

模擬行為

NetworkObjects不再支援SimulationBehaviours。將它們替換為NetworkBehaviour,並移除IOnSpawned/IOnDespawned介面,改為使用override Spawned/Despawned

代理上的固定更新網路

FixedUpdateNetwork不再預設在代理上執行。

它可以透過調用Runner.SetIsSimulated(Object, true);來手動啟用。最好在Spawned中調用它,以確保FixedUpdateNetwork立即開始運行。

場景管理

場景管理已經進行了重大更改,以允許可定址場景和額外載入。

原型附加元件

從Fusion 2開始,不再支援原型附加元件。如果轉移使用此附加元件的專案,請確保在遵循SDK升級步驟時,從Fusion資料夾中移動它,然後再將其刪除。此資料夾中的許多指令碼都可以使用前面列出的轉移訣竅進行更新,但建議在不使用這些指令碼的情況,和/或需要撰寫其更簡單的版本的情況刪除它們。

順序後/前

已刪除OrderAfterOrderBefore屬性。取而代之地,使用了Unity的執行順序。您可以在Edit > Project Settings > Script Execution Order下找到內建Fusion類型的Script Execution Order 要修改內建Fusion類型的執行順序。

要調整指令碼的執行順序,請手動將它們新增到專案設定的清單中,或者使用[預設執行順序(x)]屬性。

例如 [OrderAfter(typeof(HitboxManager))]成為[DefaultExecutionOrder(-1995)]

AOI I網路運行器回調

每當物件進入或離開客戶端的AOI區域時,都會調用兩個新的回調。使用這些回調可以相應地隱藏/顯示物件。

在Fusion 1中,取而代之地需要手動偵測進入/離開AOI。

C#

public void OnObjectExitAOI(NetworkRunner runner, NetworkObject obj, PlayerRef player)
{
}

public void OnObjectEnterAOI(NetworkRunner runner, NetworkObject obj, PlayerRef player)
{
}
Back to top