在多人連線系統中,要讓一個物件的行為能同步到所有客戶端的行為稱為 RPC (Remote Procedure Call),在 Mirror 中也不例外。
Mirror 中有提供 ClientRpc 來快速實作行為同步,但在這篇文章中我們還不會碰到這一塊的程式碼,因為 Mirror 已經實作了位置座標 (包含旋轉、縮放)、動畫和剛體同步功能,我們先介紹這幾個組件的用法。
新增並設置組件
我們繼續上一篇文章 [Mirror Networking] Network Manager、Player 物件建置教學 的進度,開啟 BasicPlayer 物件的 Inspector 視窗,為它新增 Collider、Rigidbody 和 Animator 組件,你可以依需求進行取捨,但碰撞器與剛體的行為觸發條件一樣要合法。

接下來在 BasicPlayer 物件下加入 NetworkTransform、NetworkRigidbody 與 NetworkAnimator 組件,基本上 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"); }
結果預覽
影片中的旋轉應該會看不太出來,物件閃爍的部分是動畫的同步。
關於基本座標控制、剛體與動畫的教學到這邊,有問題請於留言版提出。
謝謝您的分享~能不能出場景物件的同步教學呢?
聽起來不錯,我來規劃一下~