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;
    }
}

现在我们可以运行测试了,测试效果如下图所示:
在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值