• 您的位置:首页 > 新闻动态 > Unity3D

    Unity3d网络通信 - NetWork组件使用

    2019/5/28      点击:

    习Unity3d的过程中,经常上网查阅各位大牛的博客,受益匪浅,从今天开始写自己在学习过程中遇到的问题,总结归纳下来,方便日后复习

    这两天在学习Unity的网络模块,今天先总结Unity自带的Network组件相关使用方法

    一.网络管理物体

    搭建网络,需要先创建一个空物体用来添加网络管理组件,首先要给空物体添加以下两个组件

    注意事项: 1. OffLine Scene代表客户端连接服务器前,等待的场景(游戏大厅)

    .                   OnLine Scene代表客户端连接服务器后的场景 (游戏场景)

                      2.Spawn Info 服务器卵生信息 :  把网络预设体(必须挂有网络组件) 拖入PlayerPrefab , 服务器会把游戏对象孪生到所有连接的客户端中

    二.游戏对象

    1.Network Identity

          游戏对象(网络预设体)需要挂Network Identity组件,该组件是网络的核心,由服务器Spwan(卵生)的物体都必须具备,该组件在卵生的时候会自动分配assetID和权限

    注意事项:1.ServerOnly 勾选后物体只在服务器中存在

                  2.Local Player Authority勾选后在客户端中存在

    2.实现状态同步

     游戏对象的控制脚本需要继承NetWorkBehaviour组件(依赖于NetWorkIdentity),用来实现RPC技术和状态同步属性.
    1.Transform同步
    这个组件负责玩家对象在客户端发出移动指令后,把该玩家的移动同步到所有客户端中

    注意事项:1.Net Work Send Rate 表示同步Transform的频率

                    2.Transform Synv Mode 表示同步的模式,可以选择同步刚体组件,角色控制器等

    然后在控制脚本编写代码

        void Update() {
            if (!isLocalPlayer)   //判断是否是本地客户端
            {
                return;
            }
            float x = Input.GetAxis("Horizontal");
            float y = Input.GetAxis("Vertical");
            if (x != 0 || y != 0)
            {
                transform.position += new Vector3(x, 0, y);
            }
    }


    注意事项 1.所有网络控制脚本必须要继承 NetWorkBehaviour

                  2.在Update里需要先判断是否是本地客户端,不是的话Return~!!!  如果没有这个判断条件,在客户端发出指令,网络里所有的客户端都会执行

    2.发射子弹与减血的同步

    经过上边的步骤,已经可以实现物体在网络里的移动,但我们想要实现在网络里发射子弹,受到攻击后还要减血,这些指令都需要在服务器上执行,先来看一下NetWorkBehaviour的常用特性

    [SyncVar]    用于标识序列化变量,实现变量同步             例: (把Hp标识,就可以实现同步减血)

    [Client]        表示只能在客户端调用

    [ClientCallBack]   表示客户端执行的回调

    [Command]  表示客户端向服务端发送的命令,在服务端执行

    [ClientPrc]  表示服务端向客户端发送的命令,在客户端执行

    直接来看代码如何使用:

    //将血量设置为网络同步变量
        [SyncVar]
        float hp = 100;
        public Slider slider;       //显示血量的血条
        public GameObject bullet;   //子弹预设体
        void Start () {
            ClientScene.RegisterPrefab(bullet); //在场景注册预设体
        }
        void Update () {
            // 2.将血量的值赋给slider
            slider.value = hp / 100f;
            if (!isLocalPlayer)
            {
                return;
            }     
            if (Input.GetKeyDown(KeyCode.Q))
            {
                CmdReduceHp();
            }
            if (Input.GetKeyDown(KeyCode.T))
            {
                CmdFire();
            }
        }
        //减血的方法   标识为Command由服务器执行
        //前缀必须是Cmd 开头
        [Command]
        public void CmdReduceHp()
        {
            hp -= 10;
        }
         //发射子弹的方法
        [Command]
        public void CmdFire()
        {
            GameObject a= Instantiate(bullet, transform.position+transform.right, Quaternion.identity);
            a.GetComponent().AddForce(transform.right*100);   //给子弹添加向右的力
            NetworkServer.Spawn(a);   //由服务器卵生给连接的客户端
        }

    注意事项:1.网络预设体需要先在客户端场景里注册一下,才能正常产生              

                   2.hp赋值给Slider要写在判断是否是本地客户端前,血条才会正常同步显示

                   3.Command修饰的方法,由客户端发起,服务端执行,方法名前必须加Cmd

                   4.监听键盘事件的Iput.GetKeyDown要放在Update里,不能放在Cmd方法里!!!  (此时方法由服务器调用,无法监听键盘事件)

    3.动画的同步

       要实现游戏对象的动画同步,还需要添加一个网络组件,并给组件指定Animator,并勾选Animator里包含的动画.

    动画同步需要注意一点,过度条件是Trigger时需要由客户端发起指令,在服务端执行,再分发给各个客户端执行,其他条件正常.

    这里Animator的两个动画,attack01条件是bool,attack02条件是Trigger ,代码如下:

    Animator ani;  
        void Start()
        {
            ani = GetComponent();
        }
         void Update () {
         if (Input.GetKeyDown(KeyCode.Q)) 
            {
                ani.SetBool("attack01", !ani.GetBool("attack01"));        
            }
            if (Input.GetKeyDown(KeyCode.E))
            {
                CmdAttack02();
            }
        }
        [Command]    //服务器执行
        void CmdAttack02()
        {
            RpcPlayTrigger();
        }
        [ClientRpc]   //由服务器端调用,在客户端执行 
        void RpcPlayTrigger()
        {
            ani.SetTrigger("attack02");
        }
    希望对UNITY爱好者有抛砖引玉的疗效,敬请关注WONGLOVE获取更多UNITY精华。