This document is about: FUSION 1
SWITCH TO

This page is a work in progress and could be pending updates.

3 - Movement & Camera

概述

在Fusion 103共享中,基於玩家輸入及一個跟隨正確的玩家物件的第一人稱相機,來新增玩家移動,使得現有的場景取得擴展。

玩家移動

在Fusion中,在每個刷新更新的遊戲遊玩程式碼,比如移動,不應在Update / FixedUpdate中運行。取而代之地,應該使用FixedUpdateNetwork。這樣確保在所有客戶端上平順移動以及正確地內插補點。

建立一個新的指令碼並且命名它為PlayerMovement。讓它繼承於NetworkBehaviour而非MonoBehaviour,並且新增以下程式碼到指令碼:

C#

private CharacterController _controller;

public float PlayerSpeed = 2f;

private void Awake() {
    _controller = GetComponent<CharacterController>();
}

public override void FixedUpdateNetwork()
{
    // Only move own player and not every other player. Each player controls its own player object.
    if (HasStateAuthority == false)
    {
        return;
    }

    Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")) * Runner.DeltaTime * PlayerSpeed;


    _controller.Move(move);

    if (move != Vector3.zero)
    {
        gameObject.transform.forward = move;
    }
}

HasStateAuthority可以用於檢查客戶端是否控制一個物件。NetworkTransform只從StateAuthority同步更改到所有其他人。如果另一個客戶端更改了物件的位置,該更改將只是一個本機的更改,並且在未來以來自網路的資料來覆寫。

針對在固定更新網路中運行的程式碼,總是使用Runner.DeltaTime!

新增PlayerMovement元件到玩家預製件。

相機

有許多方法來設定一個相機(第三人稱、第一人稱等等),以及不同的方法來執行它們。在一個多人玩家遊戲中,通常需要一個跟隨本機玩家物件的單一相機。有兩個常見的方法來達成這件事。

  1. 當生成本機玩家物件時,讓它具現化一個相機。
  2. 讓相機作為場景的一部分。當生成本機玩家物件時,讓它找到相機並且設定相機的目標到它。

在這個說明中,使用第二種方式。

建立一個新的指令碼並且命名它為FirstPersonCamera。新增以下的程式碼到它:

C#

using UnityEngine;

public class FirstPersonCamera : MonoBehaviour
{
    public Transform Target;
    public float MouseSensitivity = 10f;

    private float vertialRotation;
    private float horizontalRotation;

    void LateUpdate()
    {
        if (Target == null)
        {
            return;
        }

        transform.position = Target.position;

        float mouseX = Input.GetAxis("Mouse X");
        float mouseY = Input.GetAxis("Mouse Y");

        vertialRotation -= mouseY * MouseSensitivity;
        vertialRotation = Mathf.Clamp(vertialRotation, -70f, 70f);

        horizontalRotation += mouseX * MouseSensitivity;

        transform.rotation = Quaternion.Euler(vertialRotation, horizontalRotation, 0);
    }
}

這是一個非常簡單的第一人稱相機執行方式。請注意,程式碼不含有任何多人玩家元素。您可以以任何其他適用於目標物件的相機設定,包含Cinemachine,來替換這個相機。

在場景中將FirstPersonCamera行為放在MainCamera遊戲物件上。不需要在目標中拖曳。在運行階段將透過程式碼來設定目標。

Add Networking

為了指派目標,開啟PlayerMovement指令碼。新增一個變數以儲存相機:

C#

public Camera Camera;

然後當生成玩家物件時,如果是本機玩家,則找到並設定相機。

C#

public override void Spawned()
{
    if (HasStateAuthority)
    {
        Camera = Camera.main;
        Camera.GetComponent<FirstPersonCamera>().Target = GetComponent<NetworkTransform>().InterpolationTarget;
    }
}

在初始化NetworkObjects時,請確保總是使用Spawned而非Awake/Start。在Awake/Start中,NetworkObject可能還沒有準備好使用。

有狀態授權 只在玩家控制的物件上為真,所以只有本機玩家物件而沒有其他玩家物件。

最後,因為第一人稱遊戲中,玩家角色在查看的方向上移動會稍微調整一下移動。將計算Vector3 move的列替換為:

C#

var cameraRotationY = Quaternion.Euler(0, Camera.transform.rotation.eulerAngles.y, 0);
Vector3 move = cameraRotationY * new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")) * Runner.DeltaTime * PlayerSpeed;

處理按鈕按下

Update期間,在Unity中會引發一次性輸入比如GetButtonDown及上。在Fusion中,遊戲遊玩程式碼,比如移動,應該在FixedUpdateNetwork中執行。這意味著對於準確地追蹤按鈕狀態而言,特殊處理是必要的。

請注意,在固定更新中檢查按鈕按下情況時,也會發生相同的問題。

FixedUpdateNetwork中有多個方法來捕捉這樣的輸入:

  1. 查詢Update中的向下按鈕。將結果儲存於一個布林值中,並且將其用於遊戲邏輯。在FixedUpdateNetwork結束時清除它。
  2. 使用Fusion的網路輸入NetworkButtons
  3. 使用新的Unity輸入系統,並且設定Update ModeManual Update以及在FixedUpdateNetwork中調用 InputSystem.Update。()
上述選項只適用於共享模式。當在伺服器/主機端模式中運行Fusion時,總是使用網路輸入。

跳躍

讓我們針對處理按鈕按下來執行一個示例,就是針對玩家執行一個跳躍動作。在這個案例中,使用了列在先前章節中的選項中的選項1。

新增下列變數到PlayerMovement以啟動:

C#

    public float JumpForce = 5f;
    public float GravityValue = -9.81f;

    private Vector3 velocity;
    private bool _jumpPressed;

_jumpPressed將用於追蹤按鈕狀態。velocity用於在飛行中新增人工重力到KCC。

為了輪詢向下按鈕狀態,各個Update新增下列程式碼:

C#

void Update()
{
    if (Input.GetButtonDown("Jump"))
    {
        _jumpPressed = true;
    }
}

然後在FixedUpdateNetwork結束時清除跳躍狀態:

C#

_jumpPressed = false;

以下列內容替換調用_controller.Move的列:

C#

_velocity.y += GravityValue * Runner.DeltaTime;
if (_jumpPressed && _controller.isGrounded)
{
    _velocity.y += JumpForce;
}
_controller.Move(move + _velocity * Runner.DeltaTime);

最後,在HasStateAuthority檢查後立即新增以下內容,以重新設定在地面時的速度:

C#

if (_controller.isGrounded)
{
    velocity = new Vector3(0, -1, 0);
}

回到Unity並且啟動遊戲,然後按下Start Shared Client。按下Space按鈕,然後看見角色跳躍。

下一章是共享模式基礎4 - 網路屬性

Back to top