unity3D网络基础学习(一)
最近我在进行一个小型的Unity3D(U3D)网络手游项目的开发。由于个人不习惯做笔记,所以打算通过博客的形式记录知识点,同时也为和我一样正在学习U3D的朋友们提供一个交流学习的平台。在此声明,如果文章中有错误的地方,还请大家多多指正;若有更简单的方法或扩展知识,也希望大家能相互分享学习。后续的内容可能还会穿插Unity的Editor类知识、网络资源的打包下载以及Shader的学习等。
网络编程重要概念
在学习网络编程之前,我们需要先了解几个重要的概念,否则后续的代码可能会难以理解。
1. Network.Player
Network.Player
用于获取本地 NetworkPlayer
实例,它是一个可以从网络定位玩家的数据结构。我们通过查看API可知其包含以下变量:
NetworkPlayer.ipAddress
:可获取该玩家的IP地址。NetworkPlayer.externalIP
:可获取外网的IP地址。port
和external port
:分别用于获取端口和外网端口。内网和外网的区别,简单来说,内网是指局域网,外网则是外部网络,大家可以自行查阅更详细的资料。GUID
:在初始化服务器的参数中会用到,但具体功能后续再详细说明,对其运行机制感兴趣的朋友可以自行查阅相关资料。
2. OnServerInitialized()
当调用并完成 Network.InitializeServer
时,会在服务器上调用此函数。Network.InitializeServer(connections : int, listenPort : int, useNat : bool)
用于初始化服务器,下面介绍其参数:
connections
:允许的入站连接或玩家的数量。listenPort
:要监听的端口。如果不清楚端口的概念,建议自行查阅相关资料。useNat
:用于设置NAT穿透功能。若希望服务器能够接受使用NAT穿透的连接,可将其设置为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;
}
}
上述代码中,OnGUI()
函数用于根据网络连接状态进行不同的处理,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);
}
}
StartConnect()
函数表示服务端的连接操作,提供了创建服务器和连接服务器的按钮。
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 < connectLength; i++)
{
GUILayout.Label(" 连接的IP:" + Network.connections[i].ipAddress);
GUILayout.Label(" 连接的端口:" + Network.connections[i].port);
}
if (GUI.Button(new Rect(10, 140, 100, 30), "断开连接"))
{
// 从服务器上断开连接
Network.Disconnect(200);
}
}
OnServer()
函数用于显示服务端的相关信息,包括服务端的IP地址、端口号以及连接的客户端信息,同时提供断开连接的按钮。
/// <summary>
/// 当有新的用户连接进来时
/// </summary>
void OnPlayerConnected(NetworkPlayer player)
{
Debug.Log("新连接入客户端:" + player);
SendMessage("createPlayer", player);
// networkView.RPC("OnNetworkLoaded", RPCMode.Others, player);
}
/// <summary>
/// 当现有用户断线时
/// </summary>
void OnPlayerDisconnected(NetworkPlayer player)
{
Debug.Log("清除对象: " + player);
Network.RemoveRPCs(player);
Network.DestroyPlayerObjects(player);
}
/// <summary>
/// 当前脚本作为客户端时 成功连接到服务器时 调用当前方法
/// </summary>
void OnConnectedToServer()
{
Debug.Log("客户端成功连接上服务器了!!!");
}
以上三个函数分别处理新用户连接、用户断线以及客户端成功连接到服务器的情况。
注意事项
SendMessage("createPlayer", player);
这个信息发送无法执行,因为 “createPlayer” 方法在另一个脚本中。如果有朋友想要尝试运行此脚本,可将这个方法暂时注释掉。
至此,创建连接的脚本已经完成。下次将更新信息同步的功能。