前阵子做的项目音之国度,用到了Unity的原生网络框架RPC,不如Photon之类的功能强大,但却十分好理解。
1.基本原理
服务器程序初始化一个server型的network,初始化完后,所有的客户端通过ip和端口,和服务器建立起传输的初始化,当真正需要传输数据的时候,是基于一种叫rpc的机制——远程主机调用,比如客户端想执行走的业务逻辑,首先在客户端申明走的函数的原型,但并没有具体实现,他将参数传入服务器,找到在服务器里走函数的具体的实现,执行具体逻辑,服务器再向所有客户端返回结果,完成网络同步的交互。
2.初始化服务器
if(Network.peerType==NetworkPeerType.Disconnected)
{
var error=Network.InitializeServer (12,Port,false);
switch (error)
{
case NetworkConnectionError.NoError:
console.text = Network.player.ipAddress;
break;
default:
break;
}
}
Port是一个整型数字,大致范围在几万以内,建议使用比较靠后的数字,端口被其他程序占用的可能较小。
3.客户端和服务器建立连接
public void connect_server(string ip)
{
if (Network.peerType == NetworkPeerType.Disconnected)
{
var error = Network.Connect (ip, port);
Debug.Log (error.ToString());
switch (error)
{
case NetworkConnectionError.NoError:
IP_PLAYER = Random.Range (int.MinValue,int.MaxValue);
break;
default:
break;
}
}
}
这里的ip是服务器的ip,可事先查看自己的服务器主机的ip放在这里。
这里同时还生成一个IP_PLAYER的标识符,这是因为在我的项目中,玩家很少,所以我生成了一个随机的标识符,这是发生碰撞的概率很低,所以使用了这样一个int代替一个string的ip作为标识符。
4.以注册为例,演示RPC的用法
客户端申明register的函数原型:
[RPC]
void Register(string account,string password,int info){}
服务器拥有具体的实现:
[RPC]
void Register(string account,string password,int Virtual_IP,NetworkMessageInfo info)
{
if (!dic.ContainsKey (account))
{
XmlElement xe = xml_document.CreateElement ("USERMESSAGE");
xe.InnerText = account;
xe.SetAttribute ("password",password);
xml_document.FirstChild.AppendChild (xe);
xml_document.Save (Path);
dic.Add (account, password);
GetComponent<NetworkView> ().RPC ("RegisterSucceed", RPCMode.Others, Virtual_IP);
}
else
{
GetComponent<NetworkView> ().RPC ("RegisterFailed", RPCMode.Others, Virtual_IP);
}
}
调用:
[RPC]
public void RegisterUI()
{
if (Network.peerType == NetworkPeerType.Client)
network_manager.GetComponent<NetworkView> ().RPC ("Register", RPCMode.Server, UserAccount.text,UserPassWord.text,IP_PLAYER);
else
Debug.LogError ("DisConnect");
}