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