<一>NetworkManager 类创建服务器和客户端

<1>NetworkServer类负责创建服务器监听接口,管理客户端的连接,它也负责处理游戏相关的一些特性 :玩家管理 ,监听,卵生对象和消息处理。

Server方法
静态方法↓               功能↓
Listen                    根据指定端口开启服务器
RegisterHandler   注册回调函数  (接受客户端连接请求)
Spawn                   在所有已准备的客户端上实例化物体
SpawnWithClientAuthority   跟Spawn() 方法一样 并且设置客户端权限
Destroy                 在所有客户端上删除物体
AddPlayerForConnection   将卵生的物体与客户端建立关系

Server属性
↓静态变量                ↓功能
active                     检查服务器是否开启
connections           当前所有连接的客户端列表
handles                  以字典形式返回服务器注册的所有回调方法
listenPort               服务器监听端口
localClientActive   在服务器上的客户端,即为主机是返回true
maxDelay               连接之间发送数据的最大延迟

创建服务器
需要引入using UnityEngine.NetWorking ; 系统
Button StartServerButton;
void OnEnable(){
Application.runInBackground=true;
StartServerButton=GetComponent<Button>();
StartServerButton.onClick.RemoveAllListeners;
StartServerButton.onClick.AddListener(StartServer);
}

void StartServer(){
//服务器是否打开
if(!NetworkServer.active){
//根据指定端口  开启服务器
NetworkServer.Listen(7777);
}
//接受客户端连接请求

}

<二>NetworkClient该类对象负责连接服务器,并与服务器通信(即收到服务器消息和发送消息给服务器)

Client方法
↓对象方法                 ↓功能
Connect                  根据指定IP和Port连接服务器
RegisterHandler      注册回调函数

创建客户端
需要引入using UnityEngine.Networking;系统

Button clientButton;
NetworkClient client;
void OnEnable(){
clientButton=GetComponent<Button>();
clientButton.onClick.AddListener(Connect);
}
void Connect(){
//创建了一个客户端对象
client=new NetworkClient();
//注册回调函数
client.RegisterHandler(MsgType.Connect,OnClientConnect);
//连接服务器
client.Connect("127.0.0.1",7777);
}
//成功连接服务器之后
void OnClientConnect(NetworkMessage msg){
print("连接服务器成功");

}

 ****完整代码****

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking ;
using UnityEngine.UI ;
public class NetworkMangerScr : MonoBehaviour {

    // 1.创建服务器按钮
    Button iButton;
    //8.连接服务器按钮
    Button CButton;
    //12.客户端对象
    NetworkClient m_client;
    //17.网络预设体
    public  GameObject m_prefab;
    void Awake(){
        m_client = new NetworkClient ();
        Application.runInBackground = true;
        iButton = GameObject.Find ("IButton").GetComponent <Button > ();
        CButton = GameObject.Find ("CButton").GetComponent <Button > ();
        //2.移除
        iButton.onClick.RemoveAllListeners ();
        //3.绑定
        iButton.onClick.AddListener (InitServerAction);
        //9.移除
        CButton.onClick.RemoveAllListeners ();
        //10.绑定
        CButton.onClick.AddListener (ConnectSever );

    }
    //11连接服务器的点击事件
    void ConnectSever(){
        //13.连接服务器
        m_client.Connect("127.0.0.1",3456);
        //14.注册连接成功的回调方法
        m_client.RegisterHandler (MsgType.Connect ,OnConnectSever );
    }
    //15.连接成功的回调方法
    void OnConnectSever(NetworkMessage msg){
        print ("连接服务器成功");
        //16.场景已经准备好   客户端场景准备进入Game窗口 conn 客户端连接准备
        ClientScene.Ready (msg.conn);
        //18.向服务器注册玩家预设体
        ClientScene.RegisterPrefab (m_prefab );
        //19.添加一个玩家 使用该方法之后 服务器端的MsgType.AddPlayer 注册方法就会调用
        ClientScene.AddPlayer (0);
   

    }
    //4.创建服务器的点击事件
    void InitServerAction(){
        //根据指定端口 开启服务器
        NetworkServer.Listen (3456);
        //6.接受客户端连接请求
        NetworkServer.RegisterHandler (MsgType.AddPlayer ,OnServerAddPlayer);
        //23.
        m_client =ClientScene.ConnectLocalServer ();
        m_client.RegisterHandler (MsgType.Connect ,OnConnectSever);
    }
    //7.玩家在服务器创建玩家对象的回调方法
    void OnServerAddPlayer(NetworkMessage msg){
        //20.在服务器端 实例化网络对象
        GameObject obj=Instantiate (m_prefab ,Vector3.zero ,Quaternion.identity );
        //21. 将创建的游戏对象与某个玩家建立联系,表示该obj由客户端生成
        NetworkServer.AddPlayerForConnection (msg.conn,obj,0);
        //22.将游戏对象卵生到所有客户端
        NetworkServer.Spawn (obj);
    }
    void Start () {

    }

    // Update is called once per frame
    void Update () {

    }
}
<二>Unity网络卵生
网络中 ,所有网络对象都应该由服务器产生
客户端玩家对象生成步骤:
1.客户端发请求
2.服务器接收请求后实例化客户端对象

卵生对象步骤

1.新建预设体,添加NetworkIdentity组件 标示为网络物体
2.客户端调用ClientScene.Ready() 方法告知服务器自己已准备好
3.客户端调用ClientScene.RegisterPrefab()提前 注册网络预设体
4.客户端调用ClientScene.AddPlayer()方法告诉服务器执行卵生对象的程序,参数即给将要产生卵生对象贴一个IP
5.服务器RegisterHandler-->MsgType.AddPlayer的回调AddPlayer
6.服务器在AddPlayer方法实例化物体,调用Spawn方法卵生

<三>Unity状态同步

1.NetworkIdentity组件是网络的核心 用NetworkServer.Spawn卵生的物体都必须具备该组件
该组件在卵生的时候会自动分配assetld和权限

2.NetworkBehaviour组件是一个特殊组件,它依赖NetworkIdentity组件,用来实现RPC技术和状态同步属性.
我们想实现状态同步 则网络物体的控制脚本必须继承自NetworkBehaviour

NetworkBehaviour组件包含的常用特性[Attribute]
↓特性                      ↓功能
[SyncVar]               用于标识序列化变量,实现变量同步
[Client]                   表示只能在客户端调用
[ClientCallback]     表示客户端执行的回调
[Command]            表示客户端向服务端发送的命令,在服务端执行
[ClientRpc]             表示服务端向客户端发送的命令,在客户端执行

***特别注意动画同步中 ,参数为Trigger的最为特殊 服务端不能直接执行该动画 因此需要先在客户端执行然后再在服务端执行

完整代码 (续上面代码):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking ;
using UnityEngine.UI ;
public class PlayerScript : NetworkBehaviour {
    //血量   客户端执行服务端调用
    [SyncVar]
    float hp=100f;
    public GameObject bullet;
    Slider hpSlider;
    void Awake(){
        hpSlider = transform.Find ("Canvas/HpSlider").GetComponent <Slider >();
    }
    // Use this for initialization
    void Start () {
        //卵生到客户端
        ClientScene.RegisterPrefab (bullet );
    }

    // Update is called once per frame
    void Update () {
        //实时更新血条
        hpSlider.value =hp/100f;
        //判断是不是本地客户端
        if (!isLocalPlayer) {
            return;
        }
        //控制移动
        float hor=Input.GetAxis ("Horizontal");
        float ver = Input.GetAxis ("Vertical");
        if (ver!=0 ||hor!=0) {

            transform.position += new Vector3 (hor, ver, 0f) * 5f*Time.deltaTime ;
        }
        if (Input.GetKeyDown (KeyCode.Space )) {
            //发射子弹
            CmdFire ();

        }
    }
    //发射子弹
    //由[Command]修饰的方法 表示客户端调用 服务器执行 方法的名字必须以Cmd开头
    [Command]
    void CmdFire(){

        GameObject obj = Instantiate (bullet, transform.position+transform.right, Quaternion.identity);
        obj.GetComponent <Rigidbody > ().AddForce (transform.right  *1000f);
        NetworkServer.Spawn (obj);
    }
    void OnTriggerEnter(Collider other){
        CmdDemage ();
        Destroy (other.gameObject );
    }
    [Command ]
    void CmdDemage(){
        hp -= 20f;

    }
}
   

(动画状态同步重点)完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking ;
public class PlayerController : NetworkBehaviour {
    Animator ani;
    // Use this for initialization
    void Start () {
        ani = GetComponent <Animator > ();
    }

  

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

        float ver = Input.GetAxis ("Vertical");
        float hor = Input.GetAxis ("Horizontal");
        transform.position += new Vector3 (hor,ver,0)*5f*Time.deltaTime ;
        if (Input.GetKeyDown (KeyCode.Alpha1 )) {
            //攻击
            ani.SetBool ("Attack",!ani.GetBool ("Attack"));
        }
        if (Input.GetKeyDown (KeyCode.Alpha2 )) {
            //跳跃
            CmdJump ();
        }

    }



    [Command ]
    void CmdJump(){
        //告诉服务器要执行代码 服务器去通知其他客户端执行Trigger控制的动画
        RpcJump ();
    }
    [ClientRpc ]
    void RpcJump(){
        ani.SetTrigger ("Jump");
    }
}
 

<四>RPC(远程过程调用)技术

需要引入Using UnityEngine.Networking; 系统
网络系统可以实现客户端和服务器的通信,则称之为:远程调用Remote Procedure Calls 即RPC
RPC框架可以方便实现方法调用 
Unity中有俩种类型: 

  • 客户端调用服务器方法(Command)  
  • 服务器调用客户端方法(ClientRpc)

<五>Unity网络管理器

重点:网络管理器(NetworkManager)是Unity新版网络HLAPI中的一个核心组件 ,该组件封装了网络创建,运行和Debug等各种方法初级开发者,不需要写一行代码,即可实现简单的网络游戏。

我学院网