This document is about: FUSION 2
SWITCH TO

4 - Physics

概述

Fusion 104將檢查Fusion如何在伺服器授權遊戲中與PhysX互動。

在本章節的最後,專案將允許玩家生成一個物理控制的球並與之互動。

設定

預設下,Fusion將在主機端上運行物理模擬,客戶端將跟隨。然而,與本機預測的物件相比,這將使物理物件處於不同的時間,如果這些物體碰撞,這將給物理模擬帶來問題。

雙重時間是一個複雜的主題,可以用多種方式處理——有些是徹頭徹尾的駭客行為,有些則對一般應用程式來說過於昂貴,或者不能提供玩家期望的即時回饋。不幸的是,並沒有一個適用於所有情況的簡單的解決方案。

在本教學中,我們將使用Fusion的物理附加元件來本機預測物理物件,將物理控制的物件與玩家控制的虛擬人偶同時放置。這是一個堅實的解決方案,也可以在生產中使用,但請記住,在PhysX中運行預測和重新模擬是昂貴的(也就是各個刷新中有多次)。

為了取得Physics附加元件,請前往下載頁面,選擇Unity套件並將其匯入到專案中。

物理物件

已連網、PhysX控制的物件的預製件使用與常規Unity PhysX物件相同的Rigidbody,但具有不同的Fusion元件以同步名為NetworkRigidbody的視覺效果下層物件。就網路而言,這將取代NetworkTransform

  1. 在Unity編輯器中建立一個新的空的遊戲物件
  2. 重新命名GameObjectPhysxBall
  3. 新增一個新的NetworkRigidbody3D元件。
  4. Fusion將顯示一個關於遺失NetworkObject元件的警告,請繼續並按Add Network Object。Fusion也會自動新增一個常規的Unity剛體,因為這是PhysX模擬所需要的。
  5. 新增一個球體下層到PhysxBall
  6. 在所有方向將它縮放小到0.2
  7. 將下層物件拖到上層物件上的NetworkRigidbody3D元件的InterpolationTarget中。
  8. 從球體移除碰撞器
  9. 在上層物件上建立一個新的球體碰撞器,並為其指定0.1的半徑,這樣它完全覆蓋下層物件。
  10. 新增一個新的指令碼到遊戲物件,並且稱其為PhysxBall.cs
  11. 最後拖曳整個物件到專案資料夾來建立一個預製件
  12. 儲存該場景以內嵌網路物件,並且從場景刪除預製件執行個體。
Ball Prefab
球預製件

對於物理物件,建議分離視覺效果並將其指派為Interpolation Target,但這並非總是必要的。碰撞器和剛體必須與網路剛體一起位於上層物件上。

PhysxBall指令碼

因為球是由PhysX驅動的,而網路剛體負責處理已連網資料,所以它比其運動學的表親需要更少的特殊程式碼來工作。需要新增到PhysxBall.cs中的,是幾秒鐘後取消生成球的計時器(這與運動學的球完全相同),以及設定初始前進速度的方法。

兩者都包含在Init()方法中,如下所示:

C#

using UnityEngine;
using Fusion;

public class PhysxBall : NetworkBehaviour
{
  [Networked] private TickTimer life { get; set; }

  public void Init(Vector3 forward)
  {
    life = TickTimer.CreateFromSeconds(Runner, 5.0f);
    GetComponent<Rigidbody>().velocity = forward;
  }

  public override void FixedUpdateNetwork()
  {
    if(life.Expired(Runner))
      Runner.Despawn(Object);
  }
}

輸入

為了生成球,程式碼需要按照與運動學的球相同的三個步驟進行擴展,但改為使用第二個滑鼠按鈕:

1. 網路輸入資料

NetworkInputData.cs中,簡單地新增一個行的按鈕旗標:

C#

using Fusion;
using UnityEngine;

public struct NetworkInputData : INetworkInput
{
  public const byte MOUSEBUTTON0 = 1;
  public const byte MOUSEBUTTON1 = 2;

  public NetworkButtons buttons;
  public Vector3 direction;
}

2. 基礎生成器

BasicSpawner.cs中,以與第一個滑鼠按鈕相同的方式來輪詢第二個滑鼠按鈕,並相應地設定旗標:

C#

  private bool _mouseButton0;
  private bool _mouseButton1;
  private void Update()
  {
    _mouseButton0 = _mouseButton0 || Input.GetMouseButton(0);
    _mouseButton1 = _mouseButton1 || Input.GetMouseButton(1);
  }

  public void OnInput(NetworkRunner runner, NetworkInput input)
  {
    var data = new NetworkInputData();

    ...

    data.buttons.Set(NetworkInputData.MOUSEBUTTON0, _mouseButton0);
    _mouseButton0 = false;
    data.buttons.Set(NetworkInputData.MOUSEBUTTON1, _mouseButton1);
    _mouseButton1 = false;

    input.Set(data);
  }

3. 玩家

Player.cs持有生成實際球預製件的程式碼,因此除了需要這樣的預製件參照之外,

C#

[SerializeField] private PhysxBall _prefabPhysxBall;

Player也必須調用生成,並使用先前建立的Init()方法設定速度(只是一個常數乘以最後一個向前方向)。

C#

public override void FixedUpdateNetwork()
{
  if (GetInput(out NetworkInputData data))
  {
    data.direction.Normalize();
    _cc.Move(5*data.direction*Runner.DeltaTime);

    if (data.direction.sqrMagnitude > 0)
      _forward = data.direction;

    if (HasStateAuthority && delay.ExpiredOrNotRunning(Runner))
    {
      if (data.buttons.IsSet(NetworkInputData.MOUSEBUTTON0))
      {
        delay = TickTimer.CreateFromSeconds(Runner, 0.5f);
        Runner.Spawn(_prefabBall,
          transform.position+_forward,
          Quaternion.LookRotation(_forward),
          Object.InputAuthority,
          (runner, o) =>
          {
            // Initialize the Ball before synchronizing it
            o.GetComponent<Ball>().Init();
          });
      }
      else if (data.buttons.IsSet(NetworkInputData.MOUSEBUTTON1))
      {
        delay = TickTimer.CreateFromSeconds(Runner, 0.5f);
        Runner.Spawn(_prefabPhysxBall,
          transform.position+_forward,
          Quaternion.LookRotation(_forward),           
          Object.InputAuthority,
          (runner, o) =>
          {
            o.GetComponent<PhysxBall>().Init( 10*_forward );
          });
      }
    }
  }
}

為了使已連網物理工作,在運行器物件上需要RunnerSimulatePhysics3D元件。因此,開啟BasicSpawner.cs,在StartGame函數中新增運行器元件的行之後新增以下行:

C#

gameObject.AddComponent<RunnerSimulatePhysics3D>();

最後,為了測試新球,請將建立的預製件指派到Player預製件上的Prefab Physx Ball欄位,然後組建並運行它。

下一章是 主機端模式基礎5 - 屬性更改

Back to top