学习Unet的一些过程
毕业设计的项目,需要用到手机作为控制端,这就需要用到Unity的网络模块。
因为只会设计到几个简单的按钮命令,所以不打算做多么复杂的功能,一开始打算用C#的Socket编程,但是考虑到多线程的关系觉得以后跟UI结合起来处理会比较麻烦,机智的我决定使用Unity提供的Unet网络模块。不需要太麻烦,只需要cs之间发送消息就行。
一开始我感觉自己掉进了一个坑,网上关于Unet的例子不要太少,而且很多都是基于多人游戏的。最无语的一点就是里面最牛的Commands和ClientRpc的远程调用命令以及各种变量同步只支持同一对象的不同实例间调用,简单点来说,就是客户端和服务器必须是同一个安装包,他俩只是打开方式不一样。但是我只是想做一个控制器作为客户端而已呀。但是我还是坚信,如此牛x的网络模块,肯定会支持我想要的这种傻x通信的。
我仔细看了Unity所有的关于Network的组件。最后将目标锁定在了NetworkManager上。接下来就是去看NetworkManager的API啦,果然,一拉下来我就知道没有错了
在Public Functions里存在许多On开头的方法,对Unity稍微熟悉一点的都知道以On开头的是Unity提供的回调函数,用于处理事件。同时也找到了StartClient、Host、Server这些方法。找到了常用的操纵方法和回调函数,接下来就是要找发送和接收消息的对象了。但是我没有丝毫头绪。我决定先将客户端和服务器连接成功再说。于是,我先引用到NetworkManager的对象,在手机端调用StartClient方法,在电脑端调用StartSever方法。发现二者能连接成功。
接下来就是处理一些连接事件了,在Scripting API文档里看NetworkManager类的Description。这里用一段简洁的代码清楚的介绍了如何使用这些连接事件
是的,只需要写一个类继承NetworkManager类。就可以很容易的重写回调函数,自定义连接事件了。何止爽歪歪。
然后我将原来添加的NetworkManager组件删掉,新建一个类并继承自NetworkManager。重写了一些需要用到的回调方法。完美搞定。
现在能连接成功,并且也能处理一些连接事件了,接下来就是cs之间收发消息了。根据经验,cs之间收发消息应该是依靠某种对象调用Send方法和Receive方法。继续查阅API发现有这么五个可能会用到的类NetworkServer、NetworkClient、NetworkReader、NetworkWriter、NetworkConnection。因为我在NetworkServer、NetworkClient、NetworkConnection都找到了与send有关的方法;而NetworkReader、NetworkWriter一看就知道是一个读一个写。但是却没有在NetworkServer、NetworkClient、NetworkConnection这三个类找到任何与Receive有关的方法,就觉得很奇怪。按理说有了NetworkReader、NetworkWriter就能实现我想要的功能了,但是我发现回调函数都会传递一个NetworkConnection对象,所以我还是希望直接使用NetworkConnection类,于是抛弃了Reader和Writer,把重点放在了NetworkConnection类。继续看API… 仔细查看了NetworkConnection的所以方法的介绍,发现有这么一个方法public void RegisterHandler(short msgType, Networking.NetworkMessageDelegate handler) 才意识到原来这里使用的是观察者模式。再进NetworkMessageDelegate看看这个委托的声明格式。我只需要自定义一个与NetworkMessageDelegate相同格式的方法。看看NetworkMessageDelegate的声明格式:
public delegate void NetworkMessageDelegate(Networking.NetworkMessage netMsg)。这里又涉及到了一个类: NetworkMessage,依稀中记得NetworkConnection的send方法也需要传递一个NetworkMessage对象。说明我的方向没有错,NetworkConnection的消息传递是通过NetworkMessage类来封装的。过程应该是非常明朗的。先构造一个NetworkMessage对象,将这个对象通过send发送出去,在另一端用注册的方法接收NetworkMessage对象,最后解析成自己需要的信息。那么接下来最后一步--了解NetworkMessage类,继续API…
接下来遇到一个比较棘手的问题—我找不到构造NetworkMessage对象的方法,API里没有提供构造函数,也没有找到任何有用的静态方法。打算将希望寄托到他的父类,在vs里双击选中NetworkMessage,F12转到定义。才发现他没有父类,简直握草了,似乎走进了死胡同。这时只有拿出终极武器了,百度一下… 直接搜索NetworkMessage。在这篇文章中找到了方法。仔细研究了一下,发现和我的思路几乎一样。
好了,最后来总结一下过程,先说服务器端:
1、 写一个Sever类,继承自NetworkManager。把这个类挂在一个空物体上,并在Inspector面板设置好参数
2、 写按钮点击一个事件,调用StartServer方法
3、 使用override关键字重写一些on开头的网络事件方法
4、 写一个sendMsg的方法,在方法体内调用NetworkConnection的send方法
5、 写一个public void XXX(NetworkMessage netMsg)这种声明方式的方法,处理收到的消息
6、 找一个合适的时机,调用NetworkConnection的RegisterHandler方法,将第五步定义的方法注册进来
客户端:
1、 写一个Client类,继承自NetworkManager。把这个类挂在一个空物体上,并在Inspector面板设置好参数(注意,客户端的NetworkAddress应该填写服务器端的IP,注意保持端口一致)
2、 写按钮点击一个事件,调用StartClient方法
3、 使用override关键字重写一些on开头的网络事件方法
4、 写一个sendMsg的方法,在方法体内调用NetworkConnection的send方法
5、 写一个public void XXX(NetworkMessage netMsg)这种声明方式的方法,处理收到的消息
6、 找一个合适的时机,调用NetworkConnection的RegisterHandler方法,将第五步定义的方法注册进来