[Unity] Mirror Networking 物件位置、動畫、剛體同步組件使用教學

發表於

Unity

在多人連線系統中,要讓一個物件的行為能同步到所有客戶端的行為稱為 RPC (Remote Procedure Call),在 Mirror 中也不例外。

Mirror 中有提供 ClientRpc 來快速實作行為同步,但在這篇文章中我們還不會碰到這一塊的程式碼,因為 Mirror 已經實作了位置座標 (包含旋轉、縮放)、動畫和剛體同步功能,我們先介紹這幾個組件的用法。

新增並設置組件

我們繼續上一篇文章 [Mirror Networking] Network Manager、Player 物件建置教學 的進度,開啟 BasicPlayer 物件的 Inspector 視窗,為它新增 ColliderRigidbodyAnimator 組件,你可以依需求進行取捨,但碰撞器與剛體的行為觸發條件一樣要合法。

接下來在 BasicPlayer 物件下加入 NetworkTransformNetworkRigidbodyNetworkAnimator 組件,基本上 NetworkTransform 是一定會加入的 (要同步位置、旋轉、縮放座標),NetworkRigidbody 是看你有沒有 Rigidbody 組件,以此類推。

因為這些組件是放在玩家物件上,未來我們會直接用程式碼在客戶端控制它的行為,所以要記得都要勾上 Client Authority

當這個物件所有的行為都是透過伺服器直接控制才可以不勾選 Client Authority。

注意:NetworkAnimator 不會自動去抓 Animator 組件 (如上圖),要記得自己將 Animator 拉進去。

位置、旋轉、縮放操作

還記得我們在 BasicPlayer 上掛的 BasicNetworkBehaviour 腳本嗎?請編輯此腳本,並加入以下程式碼。

控制物件座標行為的寫法跟單機的是一樣的,這部分的同步作業 NetworkTransform 組件都會幫我們完成,但是要記得在操作行為前要去檢查 hasAuthority 是否為 True,否則資料是無法同步的。

private void Update()
{
    if (!hasAuthority) return;
    float delta = .1f;
    // 位置
    Vector3 targetPos = transform.position;
    if (Input.GetKey(KeyCode.A)) targetPos.x -= delta;
    if (Input.GetKey(KeyCode.D)) targetPos.x += delta;
    transform.position = targetPos;
    // 旋轉
    Vector3 targetRotate = transform.rotation.eulerAngles;
    if (Input.GetKey(KeyCode.Q)) targetRotate.z += delta;
    if (Input.GetKey(KeyCode.E)) targetRotate.z -= delta;
    transform.rotation = Quaternion.Euler(targetRotate);
    // 縮放
    Vector3 targetScale = transform.localScale;
    if (Input.GetKey(KeyCode.W)) targetScale -= new Vector3(delta, delta, delta);
    if (Input.GetKey(KeyCode.S)) targetScale += new Vector3(delta, delta, delta);
    if (targetScale.x < 0) targetScale = Vector3.zero;
    transform.localScale = targetScale;
}

剛體操作

剛體一樣必須先檢查是否有權限操作,再進行其他物理行為。只要兩物件該有的碰撞器和剛體存在,NetworkRigidbody 會自動處理好所有的同步。

private void Update()
{
    if (!hasAuthority) return;
    Rigidbody rigid = GetComponent<Rigidbody>();
    if (Input.GetKeyDown(KeyCode.Space)) rigid.AddForce(new Vector3(0, 5, 0), ForceMode.Impulse);
}

動畫操作

動畫部分也一樣,檢查權限後直接操作即可,NetworkAnimator 會自動進行同步。

private void Update()
{
    if (!hasAuthority) return;
    Animator anim = GetComponent<Animator>();
    if (Input.GetKeyDown(KeyCode.Z)) anim.Play("Player_Highlight");
}

結果預覽

影片中的旋轉應該會看不太出來,物件閃爍的部分是動畫的同步。

關於基本座標控制、剛體與動畫的教學到這邊,有問題請於留言版提出。