最近在做一个小型的网络u3d手游项目,个人不习惯做笔记,所以通过博客的方式来记录知识点,同时也为跟我一样在学习U3D的朋友提供一些一起学习的平台。首先声明,如果有错误的地方还请大家多多指正,如果有什么简单的方法或者扩展的知识还请大家相互学习。在这以后可能还有穿插Unity的Editor类的知识,网络资源的打包下载,shader的学习等一些杂乱的知识。
首先想要学习网络的编程先来明白几个重要的概念,否则以后的代码可能会看不明白。
1.Network.Player 获取本地NetworkPlayer实例NetworkPlayer,一个可以从网络定位玩家的数据结构。我们来看一下API的查看一下包含的变量:NetworkPlayer.ipAddress IP我们可以得到这个参数的IP地址,NetworkPlayer.externalIP得到外网的IP,port和external port可以的到端口和外网的端口。内网跟外网的区别大家可以去查一查,个人理解就是一个局域网和外部网络。GUID这个我也不清楚什么东西,就是知道在初始化服务器的参数,具体功能后面再说,对其运行机制的有兴趣的朋友可以查一查。
2.OnServerInitialized()当Network.InitializeServer被调用并完成时,在服务器上调用Network.InitializeServer(connections : int, listenPort : int, useNat : bool)初始化服务器Network.Instantiate()实例化预设,我们看一看他的参数:connections是允许的入站连接或玩家的数量,listenPort是要监听的端口(如果不知道什么是端口的,自己查查看吧,我真不想说),useNat设置NAT穿透功能。如果你想要这个服务器能够接受连接使用NAT穿透,使用facilitator,设置这个为true(打脸啊,这么快就出来了)。
3.OnPlayerConnected()当一个新玩家成功连接时在服务器调用。
4.OnSerializeNetworkView() 自定义变量同步。后续会有这个函数的讲解。
5.OnPlayerDisconnected()当一个玩家从服务器上断开时在服务器端调用Network.RemoveRPCs(player)移除所有属于这个玩家的ID的RPC函数
Network.Destroy()跨网络销毁该物体(本地和远端)
6.OnDisconnectedFromServer()当失去连接或从服务器端断开时在客户端调用
7.Network.peerType端类型的状态,即disconnected, connecting, server 或 client四种NetworkPeerType 描述作为由Network.peerType返回的网络接口端类型的状态
8.Network.connections所有连接的玩家
9.NetworkView网络视图,定义什么在网络上同步和如何同步Gameobject.networkView 附属于这个游戏物体上的网络视图networkView.RPC()远程过程调用
10.Network.Disconnect() 关闭所有开放的连接并关闭网络接口。
了解了上面的函数之后,我们先做一个简单的连接。
// Use this for initialization //定义远程连接IP地址 private string remoteIP = "127.0.0.1"; //定义远程的端口号 private int remotePort = 10000; //限制连接数量为15个用户 private int connectCount=15; //是否启用网络地址转换器 private bool useNAT=false; void OnGUI() { switch (Network.peerType) { case NetworkPeerType.Disconnected: //服务器未开启时,开启服务器 StartConnect(); break; case NetworkPeerType.Server: //成功连接服务器 OnServer(); break; case NetworkPeerType.Client: break; case NetworkPeerType.Connecting: break; } }
(这尼玛贴不了图了,凑合着看吧);这段断代码做了一个简单的判断,其中Network.peerType用来判断网络的连接状态(是否连接,是客户端还是服务端);
继续:
void StartConnect(){ remoteIP=GUI.TextField(new Rect(10,30,100,20),remoteIP); if(GUI.Button(new Rect(10,50,100,30),"创建服务器")){ Network.incomingPassword="UnityNetwork"; NetworkConnectionError error=Network.InitializeServer(connectCount,remotePort,useNAT); Debug.Log(error); } if(GUI.Button(new Rect(10,85,100,30),"连接服务器")){ NetworkConnectionError error=Network.Connect(remoteIP,remotePort,"UnityNetwork"); Debug.Log(error); } } 这个函数表示服务端的连接。 void OnServer() { GUILayout.Label(" 服务端创建成功。等待连接····"); //得到的IP与端口 string ip=Network.player.ipAddress; int port=Network.player.port; GUILayout.Label(" ip地址:"+ip+".\n 端口号码:"+port); //连接到服务器的所有客户端 int connectLength=Network.connections.Length; //遍历所有客户端并获取IP与端口号 for(int i=0;i GUILayout.Label(" 连接的IP:"+Network.connections.ipAddress); GUILayout.Label(" 连接的端口:"+Network.connections.port); } if(GUI.Button(new Rect(10,140,100,30),"断开连接")) { //从服务器上断开连接 Network.Disconnect(200); } } /// /// 当有新的用户连接进来时 /// void OnPlayerConnected(NetworkPlayer player){ Debug.Log("新连接入客户端:"+player); SendMessage("createPlayer",player); //networkView.RPC("OnNetworkLoaded",RPCMode.Others,player); } /// /// 当现有用户断线时 /// void OnPlayerDisconnected(NetworkPlayer player) { Debug.Log("清除对象: " + player); Network.RemoveRPCs(player); Network.DestroyPlayerObjects(player); } /// /// 当前脚本作为客户端时 成功连接到服务器时 调用当前方法 /// void OnConnectedToServer(){ Debug.Log("客户端成功连接上服务器了!!!"); }
好了,到此为止,创建连接的脚本已经建立完成。下次更新信息同步的功能。
SendMessage("createPlayer",player);这个信息发送无法执行,因为“create Player”方法在另一个脚本中,如果有朋友想要尝试运行此脚本,将这个方法暂时注掉就可以了。