Unity官方內置網絡NetWork官方教程——拓展(三)

Unity官方內置網絡NetWork官方實例教程(一)
Unity官方內置網絡NetWork官方實例教程(二)
本篇是接上篇unet的基礎篇的一些功能的拓展主要爲以下:

  1. 代碼自定義生成玩家。
  2. 數據的同步問題。

0x00 簡介

  • OnServerReady:當有客戶端準備(Ready)時調用
  • OnServerAddPlayer:當生成對象到客戶端時調用
  • OnServerRemovePlayer:當玩家從客戶端銷燬時調用
  • OnServerDisconnect:當有客戶端斷開時調用
  • OnServerConnect:當有客戶端連接時調用
  • OnServerError:當服務器發生錯誤時調用
  • OnClientConnect:當連接到服務器時調用
  • OnClientDisconnect:當斷開服務器時調用
  • OnClientError:當網絡問題時調用
  • OnClientNotReady:告訴服務器沒準備好時調用
  • OnMatchCreate:當有一個比賽創建
  • OnMatchList:當接收到比賽列表時調用
  • OnMatchJoined:當假如比賽時調用

0X01 自定義生成玩家(位置)

自定義生成玩家即自定義位置,顏色,標籤等不同的玩家。如果我們想做一些對戰的小遊戲可以參考。

  • 在Hierarchy中創建一個空物體用來放玩家出生點,自定義命名(例子爲:SpawnPoints)。
  • 在SpawnPoints中添加相應的點(自定義命名,自定義位置)並添加NetworkStartPosition組件。如圖所示:
    在這裏插入圖片描述
  • 重寫了NetworkManager腳本,代碼如下:
public class MyNetWorkManager : NetworkManager
{
    #region 字段
    private short _tempIdCount = 1;
    //private int _tempCamDepthCount = 4;
    private NetworkStartPosition[] _spawnPoints;
    #endregion

    #region 系統方法
    // Use this for initialization
    void Start()
    {
        _spawnPoints = FindObjectsOfType<NetworkStartPosition>();

        #region 測試
        //foreach (var item in _spawnPoints)
        //{
        //    Debug.Log(item.name);
        //}
        #endregion
    }
    #endregion

    #region NetWork方法
    /// <summary>
    /// 添加玩家
    /// </summary>
    /// <param name="conn">連接方式</param>
    /// <param name="playerControllerId">玩家id</param>
    public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
    {
        playerControllerId = _tempIdCount;
        GameObject player = (GameObject)Instantiate(playerPrefab, Vector3.zero, Quaternion.identity);
        player.name = "Player_" + playerControllerId;

        if (_spawnPoints != null)
        {
            player.transform.position = _spawnPoints[playerControllerId - 1].transform.position;
            player.transform.rotation = _spawnPoints[playerControllerId - 1].transform.rotation;
        }
        NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
        _tempIdCount += 1;
        // _tempCamDepthCount -= 1;
    }
    #endregion
 #region 私有方法
    /// <summary>
    /// 設置同步變量初始化值
    /// </summary>
    /// <param name="tempObj">實例的物體</param>
    /// <param name="_syncColor">顏色</param>
    /// <param name="layerInt">j20父物體層</param>
    /// <param name="layerInt_Collider">雷達碰撞層</param>
    /// <param name="layerInt_Receive">雷達接收層</param>
    /// <param name="tagStr">j20父物體標籤</param>
    /// <param name="missileStr">導彈池對應字符串</param>
    /// <param name="fireStr">開火池對應字符串</param>
    void SetSyncVariable(GameObject tempObj, Color _syncColor, int layerInt, int layerInt_Collider, int layerInt_Receive, string tagStr, string missileStr, string fireStr)
    {
        tempObj.GetComponent<FighterSyncControl>()._syncColor = _syncColor;
        tempObj.GetComponent<FighterSyncControl>()._syncLayerInt = layerInt;
        tempObj.GetComponent<FighterSyncControl>()._syncLayerInt_Collider = layerInt_Collider;
        tempObj.GetComponent<FighterSyncControl>()._syncLayerInt_Receive = layerInt_Receive;
        tempObj.GetComponent<FighterSyncControl>()._syncTagStr = tagStr;
        tempObj.GetComponentInChildren<FighterSyncControl>()._syncMissilePoolStr = missileStr;
        tempObj.GetComponentInChildren<FighterSyncControl>()._syncFilePoolStr = fireStr;
    }
    #endregion
}

在每次加入玩家的時候都會根據位置點,自定義初始位置,效果如圖所示:
在這裏插入圖片描述

0X03 自定義其他變量

自定義顏色,標籤,層
修改上面自定義玩家的腳本,新增一些內容,如下:

 /// <summary>
    /// 添加玩家
    /// </summary>
    /// <param name="conn">連接方式</param>
    /// <param name="playerControllerId">玩家id</param>
    public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
    {
        playerControllerId = _tempIdCount;
        GameObject player = (GameObject)Instantiate(playerPrefab, Vector3.zero, Quaternion.identity);
        switch (playerControllerId)
        {
            case 1:
                SetSyncVariable(player, Color.red, 11, 14, 19, "Friendly", "missile_Instantiate_f", "Particle_missile_fire_f");
                break;
            case 2:
                SetSyncVariable(player, Color.blue, 15, 13, 17, "Enemy", "missile_Instantiate_e", "Particle_missile_fire_e");

                break;
            case 3:
                SetSyncVariable(player, Color.blue, 15, 13, 17, "Enemy", "missile_Instantiate_e", "Particle_missile_fire_e");

                break;
            case 4:
                SetSyncVariable(player, Color.red, 11, 14, 19, "Friendly", "missile_Instantiate_f", "Particle_missile_fire_f");
                break;
            default:
                break;
        }
        player.name = "Player_" + playerControllerId;

        if (_spawnPoints != null)
        {
            player.transform.position = _spawnPoints[playerControllerId - 1].transform.position;
            player.transform.rotation = _spawnPoints[playerControllerId - 1].transform.rotation;
        }
        NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
        _tempIdCount += 1;
        // _tempCamDepthCount -= 1;
    }
    

效果如圖所示:
在這裏插入圖片描述
在這裏插入圖片描述
如圖可見已經修改成功,下一步就是測試數據是否同步。

0X04 數據同步

  • 首先寫一個飛機接收同步數據的腳本,並且並掛載在飛機身上,自定義命名(例子名稱:FighterSyncControl)代碼如下:
public class FighterSyncControl : NetworkBehaviour
{

    #region 變量
    private Transform[] allObj;
    private GameObject curFighter;

    #region 飛機同步變量
    [SyncVar] [HideInInspector] public Color _syncColor;        // 顏色

    // 同步標籤和層
    [SyncVar] [HideInInspector] public int _syncLayerInt;
    [SyncVar] [HideInInspector] public int _syncLayerInt_Collider;
    [SyncVar] [HideInInspector] public int _syncLayerInt_Receive;
    [SyncVar] [HideInInspector] public string _syncTagStr;
    [SyncVar] [HideInInspector] public int _syncDefTagStr;
    [SyncVar] [HideInInspector] public string _syncDefLayerInt;

    // 腳本變量
    [SyncVar] [HideInInspector] public string _syncMissilePoolStr;
    [SyncVar] [HideInInspector] public string _syncFilePoolStr;
    #endregion

    #endregion

    #region 系統方法
    private void Awake()
    {
        curFighter = gameObject.GetComponentInChildren<UI_show_info_a>().gameObject;
    }

    // Use this for initialization
    void Start()
    {

        allObj = curFighter.GetComponentsInChildren<Transform>(true);
        foreach (Transform item in allObj)
        {
            SetRedOrBule(_syncLayerInt, _syncTagStr, _syncLayerInt_Collider, _syncLayerInt_Receive, _syncMissilePoolStr, _syncFilePoolStr);
        }

        SetScriptVariable(_syncColor);

    }

    // Update is called once per frame
    void Update()
    {
        #region 測試
        if (Input.GetMouseButtonDown(0))
        {//判斷鼠標是否按下
            // 從攝像機開始,到屏幕觸摸點,發出一條射線
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            // 撞擊到了哪個3D物體
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit))
            {
                Debug.Log(hit.transform.tag);//打印出碰撞到的節點的名字
            }
        }
        #endregion
    }

    #endregion

    
    /// <summary>
    ///  設置紅藍
    /// </summary>
    /// <param name="layerInt">層值</param>
    /// <param name="tagStr">標籤值</param>
    private void SetRedOrBule(int j20_layerInt, string tagStr, int radaCollider_layerInt, int radaRec_layerInt, string missileStr, string fireStr)
    {
        foreach (Transform item in allObj)
        {
            // 測試:單獨給某個賦值
            if (item.name.Equals("J20_beta"))
            {
                item.gameObject.tag = tagStr;
                item.gameObject.layer = j20_layerInt;
            }
            if (item.name.Equals("rada_scan_collider"))
            {
                item.gameObject.layer = radaCollider_layerInt;
            }
            if (item.name.Equals("rada_receive_collider"))
            {
                item.gameObject.layer = radaRec_layerInt;
            }
        }
        curFighter.GetComponent<UI_show_info_a>().missile_inpool = missileStr;
        curFighter.GetComponent<UI_show_info_a>().fire_inpool = fireStr;
    }

    /// <summary>
    /// 給固定的腳本變量賦值(同步變量)
    /// </summary>
    private void SetScriptVariable(Color tempColor)
    {
        curFighter.transform.Find("fighter_blue_type_f22").GetComponent<MeshRenderer>().material.color = tempColor;
    }
}

現在我們可以運行測試了,測試效果如下圖所示:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章