最近项目需要做hololens物体同步,他自带的UWP的延时很高,找一种延迟小的解决方案,我打算用socket的封装一个传输层,后来团队决定用NetWorking先试试,我就做了一个简单的demo。在unity5.x之前,unity用RPC通信,在5.x之后,我发现很多API被更改了,新的API加了NetworkServer,NetworkClient。这两个API用起来特别方便。
NetworkServer这个类提供很多静态类,不用创建实例,直接调用listen监听端口就行如下所示:
private int _serverPort = 10000;
private string _serverIP = “192.168.3.131”;
NetworkServer.Listen(_serverIP, _serverPort);
它还提供了一个RegisterHandler方法,用来注册一些事件,如接收,连接状态,连接错误等,示例代码如下:
NetworkServer.RegisterHandler(65, OnServerReceived);
还有一个UnregisterHandler方法,用来取消事件的触发,如下所示:
NetworkServer.UnregisterHandler(65);
NetWorkClient这个类必须得创建实例了,他内部没有创建实例,但是使用方法大致和NetWorkServer类似。
private IPEndPoint _remotePoint = new IPEndPoint(new IPAddress(new byte[] { 192,168, 3, 131 }), _clientPoint);
NetworkClient _client = new NetworkClient();
_client.RegisterHandler(65, OnClientReceived);
_client.UnregisterHandler(65);
以下是示例代码:
server端:
public class NewServer : Common
{
[SerializeField]
private Transform trans;
private bool _isInit = false;
private short userMsg = 64;
// Use this for initialization
void Start()
{
Init();
}
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.Keypad1))
{
ServerSend(1, trans.position);
_isInit = true;
}
if(_connection!=null&& _connection.isConnected&& _isInit)
{
ServerSend(2, trans.position);
}
}
private int _serverPort = 10000;
private string _serverIP = "192.168.3.131";
private NetworkConnection _connection;
private void Init()
{
this.Invoke("Setup", 5.0f);
}
public void ServerSend(int cmd, Vector3 position)
{
if (NetworkServer.active)
{
UserMessage msg = new UserMessage();
msg.Cmd = cmd;
msg.Position = position;
NetworkServer.SendToClient(_connection.connectionId, userMsg, msg);
ShowMsg("Server send finished");
}
}
private void OnServerReceived(NetworkMessage netMsg)
{
UserMsg Msg = netMsg.ReadMessage<UserMsg>();
ShowMsg("Server get:" + Msg.Message);
}
private void OnServerConnected(NetworkMessage netMsg)
{
_connection = netMsg.conn;
ShowMsg("One client connected to server");
}
private void OnServerDisconnected(NetworkMessage netMsg)
{
ShowMsg("One client connected from server");
}
private void OnServerError(NetworkMessage netMsg)
{
UnRegisterHandler();
ShowMsg("Server error");
}
private void ShowMsg(string msg)
{
Debug.Log(msg);
}
public override void Setup()
{
if (!NetworkServer.active)
{
ShowMsg("setup server");
RegisterHandler();
NetworkServer.Listen(_serverIP, _serverPort);
if (NetworkServer.active)
{
ShowMsg("Server setup ok.");
}
}
}
public override void ShutDown()
{
if (NetworkServer.active)
{
UnRegisterHandler();
NetworkServer.DisconnectAll();
NetworkServer.Shutdown();
if (!NetworkServer.active)
{
ShowMsg("shut down server");
}
}
}
public override void RegisterHandler()
{
NetworkServer.RegisterHandler(MsgType.Connect, OnServerConnected);
NetworkServer.RegisterHandler(MsgType.Disconnect, OnServerDisconnected);
NetworkServer.RegisterHandler(MsgType.Error, OnServerError);
NetworkServer.RegisterHandler(64, OnServerReceived);
}
public override void UnRegisterHandler()
{
NetworkServer.UnregisterHandler(MsgType.Connect);
NetworkServer.UnregisterHandler(MsgType.Disconnect);
NetworkServer.UnregisterHandler(MsgType.Error);
NetworkServer.UnregisterHandler(64);
}
}
Client端:
public class NewClient :Common
{
// Use this for initialization
void Start()
{
Init();
}
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.C))
{
Setup();
}
if (Input.GetKeyDown(KeyCode.Q))
{
ShutDown();
}
}
private void OnApplicationQuit()
{
ShutDown();
}
private NetworkClient _client = null;
private const int _clientPoint = 10000;
private IPEndPoint _remotePoint = new IPEndPoint(new IPAddress(new byte[] { 192,168, 3, 131 }), _clientPoint);
private void Init()
{
_client = new NetworkClient();
}
private void ShowMsg(string msg)
{
Debug.Log(msg);
}
public void ClientSend(int cmd, Vector3 position)
{
if (_client.isConnected)
{
UserMessage msg=new UserMessage() { Cmd = cmd, Position = position };
if (_client.Send(userMsg, msg))
{
ShowMsg("Client send finished");
}
}
}
private GameObject _cube;
private Vector3 temp;
private void OnClientReceived(NetworkMessage netMsg)
{
UserMessage msg = netMsg.ReadMessage<UserMessage>();
ShowMsg("Client received");
switch (msg.Cmd)
{
case 1:
{
_cube= GameObject.CreatePrimitive(PrimitiveType.Cube);
_cube.transform.position = msg.Position;
_cube.SetActive(true);
}
break;
case 2:
{
if (_cube != null)
{
temp = msg.Position- _cube.transform.position;
_cube.transform.Translate(temp);
}
}
break;
}
}
private void OnClientConnected(NetworkMessage netMsg)
{
ShowMsg("Client connected to server");
}
private void OnClientDisconnected(NetworkMessage netMsg)
{
ShowMsg("Client disconnected from server");
}
private void OnClientError(NetworkMessage netMsg)
{
UnRegisterHandler();
ShowMsg("Client error");
}
public override void RegisterHandler()
{
_client.RegisterHandler(MsgType.Connect, OnClientConnected);
_client.RegisterHandler(MsgType.Disconnect, OnClientDisconnected);
_client.RegisterHandler(MsgType.Error, OnClientError);
_client.RegisterHandler(64, OnClientReceived);
}
public override void Setup()
{
if (_client != null && !_client.isConnected)
{
RegisterHandler();
_client.Connect(_remotePoint);
}
}
public override void ShutDown()
{
if (_client.isConnected)
{
UnRegisterHandler();
_client.Disconnect();
}
}
public override void UnRegisterHandler()
{
_client.UnregisterHandler(MsgType.Connect);
_client.UnregisterHandler(MsgType.Disconnect);
_client.UnregisterHandler(MsgType.Error);
_client.UnregisterHandler(64);
}
}
消息类:
/// <summary>
/// cmd 1 初始化 2 位置同步
/// </summary>
public class UserMessage : MessageBase
{
public int Cmd;
public Vector3 Position;
}
public abstract class Common : MonoBehaviour
{
public abstract void Setup();
public abstract void ShutDown();
public abstract void RegisterHandler();
public abstract void UnRegisterHandler();
}
源码已经上传csdn,下载地址: