目前當玩家血量歸零時,除了在console視窗中顯示文字外,不會發生任何事,現在我們要將此範例修改的更像遊戲,當玩家的血量歸零,將會被傳送到起始位置並恢復血量。
接下來我們會使用[ClientRpc]屬性,這是另一個狀態同步工具。
加上ClientRpc的函式會從;帶有NetworkIdentity元件,並且是從伺服器生成的任意物件執行,即使在伺服器上呼叫帶有ClientRpc的函式,它也會在用戶端上執行。
先前提過的Command和ClientRpc相反,Command是在用戶端上呼叫,伺服器上執行。
要在一個函式前加上ClientRpc,要使用 [ClientRpc]變數,而且函式名稱前必須加上Rpc。此函數會在伺服器呼叫它時,於用戶端上執行。任何需要的變數會自動傳送給用戶端,更多關於[ClientRpc]變數的資訊,可以參考這裡。
要使用生成功能我們需要新增一個Respawn函式在Health腳本中,而且要在玩家血量歸零時,在伺服器上由TakeDamage函式呼叫它。
開啟Health腳本,修改並新增以下內容,首先在下方新增帶有[ClientRpc]變數的函式Respawn,Respawn會把判斷成死亡的玩家物件移動回(0, 0, 0)座標點,接著修改if(currentHealth == 0)中的內容,將當前血量currentHealth改為最大值maxHealth,並且呼叫Respawn :
using UnityEngine; using UnityEngine.UI; using UnityEngine.Networking; using System.Collections; public class Health : NetworkBehaviour { public const int maxHealth = 100; [SyncVar(hook = "OnChangeHealth")] public int currentHealth = maxHealth; public RectTransform healthBar; public void TakeDamage(int amount) { if (!isServer) return; currentHealth -= amount; if (currentHealth <= 0) { currentHealth = maxHealth; // called on the Server, but invoked on the Clients RpcRespawn(); } } void OnChangeHealth (int currentHealth ) { healthBar.sizeDelta = new Vector2(currentHealth , healthBar.sizeDelta.y); } [ClientRpc] void RpcRespawn() { if (isLocalPlayer) { // move back to zero location transform.position = Vector3.zero; } } }在範例中,用戶端能控制本機玩家物件的位置,這是因為玩家物件在用戶端上有本機權限(local authority)。如果伺服器在玩家物件血量歸零時,把它設回起始點,但用戶端會在擁有權限時覆蓋伺服器的動作。
為了避免這種情況,伺服器會命令自己的用戶端;如果有帶著ClientRpc的函式,優先執行這段程式,在本範例就是將玩家物件移動到起始點。另外玩家物件帶有NetworkTransform,所以位置會同步於所有用戶端。
現在我們編譯後可以進行測試,測試連線時結果的方法點我。
目前玩家對其他玩家做攻擊,並且將它的生命值歸零時,該名玩家會被送回原點並回復所有生命值。
上一篇:連線時的玩家血量
下一篇:處理非玩家角色物件
建立一個簡單的多人連線範例
沒有留言:
張貼留言