2018年4月24日 星期二

【Unity官方教學分享】新增多人連線時的射擊功能

網頁連結

在本教學中將在子彈物件上新增網路功能,我們必須對Bullet prefab及腳本做更新。
首先,Bullet prefab需要NetworkIdentity元件讓網路系統能辨識它,接著需要NetworkTransform同步移動和旋轉,最後必須在NetworkManager的Spawnable Prefab上註冊。
  • 在project視窗下點擊Bullet prefab
  • 新增元件Network->NetworkIdentity
  • 新增元件Network->Network Transform
  • 將Network Transform下的Network Send Rate設為0
子彈在射出後並不會改變方向或速度,所以不需要做移動資訊的更新,每個用戶端可以確實地計算出子彈位置,透過將Network Send Rate設為0,可以讓網路資料流量變少以達到提高效能的結果。
  • 點擊Hierarchy視窗下的NetworkManager
  • 在NetworkManager元件下找到Spawn Info並展開
  • 看下Registered Spawnable Prefabs清單旁的+按鈕新增一個項目
  • 將Bullet prefab拖曳上去
在先前我們談到如何在網路環境中製作移動系統,在多人連線的系統下,基本上伺服器和所有用戶端,會同時在相同物件上執行相同的程式碼,那時我們使用isLocalPlayer來讓各用戶端判斷自己的物件,並只針對該物件做控制。

現在我們要新增的是另一個控制屬性 [Command] , [Command] 屬性代表在它底下的函式將由用戶端呼叫,但由伺服器執行,該函數中的任何參數將透過Command自動傳給伺服器,Command只能由本機玩家送出,當一個函式要製作成網路Command時,必須以"Cmd"開頭命名,更多關於[Command] 的資訊請點這裡

現在我們把PlayerController腳本打開,找到Fire函式並在它上面新增[Command] ,並將Fire重新命名為CmdFire。
[Command]
void CmdFire()
接下來要談的是多人連線中一個有點特別的概念;Network Spawning(網路生成)。
"Spawn"在多人連線中不僅僅是"生成",更代表在伺服器及所有用戶端上產生一個物件。這個物件將由Spawning系統管理;當這個物件在伺服器上有狀態更新時,系統會發送狀態資訊給所有用戶端,例如當某用戶端物件被銷毀,伺服器就會將此狀態發送給所有用戶端,當伺服器上的物件被銷毀,用戶端的該物件也將被銷毀,而且該物件會被新增至伺服器管理的物件集合中,以便讓後來加入的其他用戶知道該物件的正確狀態。更多關於Network Spawning的資訊,可以參考這裡

在CmdFire中新增NetworkServer.Spawn。
NetworkServer.Spawn(bullet);
完成後PlayerController腳本會像這樣:
using UnityEngine;
using UnityEngine.Networking;

public class PlayerController : NetworkBehaviour
{
    public GameObject bulletPrefab;
    public Transform bulletSpawn;

    void Update()
    {
        if (!isLocalPlayer)
        {
            return;
        }

        float x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
        float z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;

        transform.Rotate(0, x, 0);
        transform.Translate(0, 0, z);

        if (Input.GetKeyDown(KeyCode.Space))
        {
            CmdFire();
        }
    }

    // This [Command] code is called on the Client …
    // … but it is run on the Server!
    [Command]
    void CmdFire()
    {
        // Create the Bullet from the Bullet Prefab
        GameObject bullet = (GameObject)Instantiate(
            bulletPrefab,
            bulletSpawn.position,
            bulletSpawn.rotation);

        // Add velocity to the bullet
        bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 6;

        // Spawn the bullet on the Clients
        NetworkServer.Spawn(bullet);

        // Destroy the bullet after 2 seconds
        Destroy(bullet, 2.0f);
    }

    public override void OnStartLocalPlayer ()
    {
        GetComponent<MeshRenderer>().material.color = Color.blue;
    }
}
到這裡我們就像先前一樣測試結果,現在看下空白鍵應該可以在所有用換端上顯示正確的結果,每位玩家應該都能夠將子彈射到其他人身上。
但是目前此射擊功能不會造成任何影響,所以在下一篇我們會製作玩家血量。

上一篇:射擊(單機)
下一篇:玩家血量(單機)

建立一個簡單的多人連線範例

沒有留言:

張貼留言

【自製小遊戲】水平思考猜謎(海龜湯)

遊戲連結 海龜湯的玩法是由出題者提出一個難以理解的事件,參與猜題者可以提出任何問題以試圖縮小範圍並找出事件背後真正的原因。但出題者僅能以「是」、「不是」或「沒有關係」來回答問題。 本遊戲蒐集各種論壇、平台的42個題目,提供給想玩海龜湯卻愁找不到題目的你們。 ...