Unity3D - 聯網射擊小遊戲

Unity3D - 聯網射擊小遊戲


視頻地址
GITHUB地址

遊戲效果

總體效果1

總體效果2

遊戲實現

  1. 第一步是在項目中建立 NetworkManager 對象:
    網絡管理空對象設置git

    • 從菜單 Game Object -> Create Empty 添加一個新的空遊戲對象。
    • 在層次結構視圖中選擇它。
    • 將對象重命名爲「NetworkManager」,使用右鍵上下文菜單中或單擊對象的名稱並鍵入。
    • 在對象的檢查器窗口中,單擊添加組件按鈕
    • 找到組件 Network -> NetworkManager 並將其添加到對象。該組件管理遊戲的網絡狀態。
    • 找到組件 Network -> NetworkManagerHUD 並將其添加到對象。該組件在您的遊戲中提供了一個簡單的用戶界面來控制網絡狀態
  2. 將場記掛載到網絡空對象上建立遊戲場景:github

    public class FirstSceneController : MonoBehaviour {
    
        // Use this for initialization
        void Start () {
            Instantiate(Resources.Load<GameObject>("Prefabs/Plane"), new Vector3(0, -0.5f, 0), Quaternion.identity);
        }
        // Update is called once per frame
        void Update()
        {
    
        }
    }
  3. 設置玩家對象預製服務器

    • 玩家預製設置:
      玩家設置
    • 下一步是設置表明遊戲中玩家對象的 Unity Prefab。默認狀況下,NetworkManager 經過克隆玩家預製來爲 Client 實例化玩家對象。在這個例子中,玩家對象將是一個簡單的立方體。
    • 從菜單 Game Object -> 3D Object -> Cube 建立一個新的立方體。
    • 在層次視圖中找到該立方體並選擇它。
    • 將對象重命名爲 「PlayerCube」。
    • 在對象的檢查器窗口中,單擊添加組件按鈕。
    • 將組件 Network -> NetworkIdentity 添加到對象。該組件用於標識服務器和客戶端之間的對象。
    • 將 NetworkIdentity 上的 「Local Player Authority」 複選框設置爲 true。這將容許客戶端控制玩家對象的移動
    • 將立方體對象拖放到資源窗口中製做預製件。建立一個名爲 「PlayerCube」 的預製件
    • 從場景中刪除 PlayerCube 對象
  4. 聯網玩家對象的運動網絡

    • 註冊玩家預製:
![註冊玩家預製](https://pmlpml.github.io/unity3d-learning/images/ch13/UNetTut5.png)
* 編寫 PlayerMove 腳本,使玩家的移動被聯網同步:
```cs
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.Networking;

    public class PlayerMove : NetworkBehaviour
    {

        public GameObject bulletPrefab;
        private Camera myCamera;

        public override void OnStartLocalPlayer()
        {
            GetComponent<MeshRenderer>().material.color = Color.red;
            GetComponent<Rigidbody>().freezeRotation = true;
            myCamera = Camera.main;
        }

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

            var x = Input.GetAxis("Horizontal");
            var z = Input.GetAxis("Vertical") * 0.1f;
            //移動和旋轉
            transform.Translate(0, 0, z * 0.7f);
            transform.Rotate(0, x, 0);
            myCamera.transform.position = transform.position + transform.forward * -3 + new Vector3(0, 4, 0);
            myCamera.transform.forward = transform.forward + new Vector3(0, -0.5f, 0);
            if (Input.GetKeyDown(KeyCode.Space))
            {
                CmdFire();
            }
            //防止碰撞發生後的旋轉
            if (this.gameObject.transform.localEulerAngles.x != 0 || gameObject.transform.localEulerAngles.z != 0)
            {
                gameObject.transform.localEulerAngles = new Vector3(0, gameObject.transform.localEulerAngles.y, 0);
            }
            if (gameObject.transform.position.y != 0)
            {
                gameObject.transform.position = new Vector3(gameObject.transform.position.x, 0, gameObject.transform.position.z);
            }
        }

        [Command]
        void CmdFire()
        {
            // This [Command] code is run on the server!

            // create the bullet object locally
            var bullet = (GameObject)Instantiate(
                bulletPrefab,
                new Vector3((transform.position + transform.forward).x,0.2f,(transform.position + transform.forward).z),
                Quaternion.identity);

            bullet.GetComponent<Rigidbody>().velocity = transform.forward * 4;

            // spawn the bullet on the clients
            NetworkServer.Spawn(bullet);

            // when the bullet is destroyed on the server it will automaticaly be destroyed on clients
            Destroy(bullet, 3.0f);      
        }
    }
```
  1. 聯網子彈。建立一個球體的子彈元素,添加rigibody和球狀碰撞組件添加進Spawn Info中的註冊預製目錄中:
    子彈設置
    網絡子彈ide

    • 子彈碰撞腳本:
    public class Bullet : MonoBehaviour {
        void OnCollisionEnter(Collision collision)
        {
            var hit = collision.gameObject;
            var hitCombat = hit.GetComponent<Combat>();
            if (hitCombat != null)
            {
                hitCombat.TakeDamage(10);
                Destroy(gameObject);
            }
            else
            {
                Destroy(gameObject);
            }
        }
    }

實現難點

  • 實現第三人稱視角時,一開始想的辦法是將攝像機綁定爲遊戲對象的子元素。可是在聯機時,因爲攝像機優先級相同優先渲染後加載的,全部視角會切換到後進入的人身上。全部只能採用移動攝像機,使攝像機永遠在第三人稱的固定位置跟隨的方式解決。this

    //添加到PlayerMove腳本中的相應部分
    public override void OnStartLocalPlayer(){
                private Camera myCamera;
    
                public override void OnStartLocalPlayer()
                {
                    myCamera = Camera.main;
                }
    
                void Update()
                {
                    myCamera.transform.position = transform.position + transform.forward * -3 + new Vector3(0, 4, 0);
                    myCamera.transform.forward = transform.forward + new Vector3(0, -0.5f, 0);
                }
    }
相關文章
相關標籤/搜索