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同步更改到所有其他人。如果另一個客戶端更改了物件的位置,該更改將只是一個本機的更改,並且在未來以來自網路的資料來覆寫。
新增PlayerMovement元件到玩家預製件。
相機
有許多方法來設定一個相機(第三人稱、第一人稱等等),以及不同的方法來執行它們。在一個多人玩家遊戲中,通常需要一個跟隨本機玩家物件的單一相機。有兩個常見的方法來達成這件事。
- 當生成本機玩家物件時,讓它具現化一個相機。
- 讓相機作為場景的一部分。當生成本機玩家物件時,讓它找到相機並且設定相機的目標到它。
在這個說明中,使用第二種方式。
建立一個新的指令碼並且命名它為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遊戲物件上。不需要在目標中拖曳。在運行階段將透過程式碼來設定目標。
 
為了指派目標,開啟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中有多個方法來捕捉這樣的輸入:
- 查詢Update中的向下按鈕。將結果儲存於一個布林值中,並且將其用於遊戲邏輯。在FixedUpdateNetwork結束時清除它。
- 使用Fusion的網路輸入與NetworkButtons。
- 使用新的Unity輸入系統,並且設定Update Mode為Manual Update以及在FixedUpdateNetwork中調用InputSystem.Update。()
跳躍
讓我們針對處理按鈕按下來執行一個示例,就是針對玩家執行一個跳躍動作。在這個案例中,使用了列在先前章節中的選項中的選項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