关于Unity的网络框架
注:Unity 5.1里引入了新的网络框架,未来目标应该是WOW那样的,现在还只是个P2P的架子。
网络的框架,无非是如何管理网络数据的收发,通信双方如何约定协议。之前做的框架与GameObject无关,网络是看不到GameObject这一层的,看到的是事务,比如例如进入场景等。在Unity里,GameObject自己可以有网络数据的处理能力,网络行为基于GameObject搭建。最大的不同是客户端服务器运行的是同一套机制,服务器上有客户端有的所有东西。uLink相比Unity自己那套东西来说,实现了更多的功能。这里打算对这类的网络进行下分析。
Unity规定,网络行为只能有RPC和状态同步两种机制,非此即彼。Unity的networkview组件实现了这种机制,从Networkview的编辑界面上看,会有疑惑,因为看起来networkview监听的是一个component,那是不是networkview监听的是脚本里的RPC和状态同步数据呢,答案是非也。If you are not directly sending data, just using RPC calls, then you can turn off synchronization (no data directly sent) and nothing needs to be set as the Observed property.这句话的意思就是说,networkview里设置observed component,只是为状态同步的。那么RPC机制是如何做的?RPC calls just need a single network view present so you don’t need to add a view specifically for RPC if a view is already present.意思就是说RPC调用不需要专门给gameobject加一个netview,只要有一个就行了,也许是某个用来做状态同步的Netview。
If you want to use Remote Procedure Calls in your script all you need is a NetworkView component present in the same GameObject the script is attached to. The NetworkView can be used for something else, or in case it’s only used for sending RPCs it can have no script observed and state synchronization turned off.
由于Unity是C/S同构,同一个GameObject存在于C和S上,C可以直接调用
workView.RPC ("PlayerFire", RPCMode.All);
同时,必须要提供一个带[RPC]表示的函数
[RPC]
void PlayerFire () {
}
这样,收到RPC调用的端,被告知说有一个GameObject上id为xxx的netview,其component里有一个名称是PlayerFire的RPC,你去找到它,并执行。
对于viewID,Unity这种可以通过控制实例化GameObject,来确保gameobject在网络上的同时存在,从而可以确保同一个gameobject,他的viewID相同。uLink里的实现是The viewID is used internally in uLink to identify the sender and target game object.说明viewID和gameobject是一一对应的。关于ID的分配方式一部分静态,双方约定;一部分是动态,由服务器分配。uLink是这么解释手动分配ID,即静态的ID:The other option is to assign manual viewIDs to game objects in the scene.Make sure you assign the same viewID to the game object in the client scene and the corresponding game object in the server scene. This is commonly used for static objects like chat windows, doors, elevators and trigger zones.
关于RPC到底是监听一个脚本还是一个GameObject?uLink里有这么一句话:The RPC calling code will use the attached uLinkNetworkView
component to invoke all PrintText()
functions in any scripts attached to this same GameObject
on all other clients (and the server) if this code is executed on one of the clients.所以至少uLink是会扫描整个GameObject的。
uLink里不推荐在一个gameobject上使用多个netview,目的有两个,一是为了降低出bug的风险,另外是简化组件结构,便于维护。要监听多个component,它提供了一个observerList。
uLink里怎么做状态同步呢?其增加了一个observerList的组件,可以往里面放置一组component,然后会为每个component生成一个处理器。当收到一个Netview id的同步请求后,ulink找到这个netview id,调用对应的netview的observerList里的托管函数,把bitstream传进去,注意这个bitstream,他是顺序放置数据的,例如有三条数据,那么这个流里面是顺序摆放,然后逐个解析。
为了搞明白一些细节,这里分析两个demo,一个是LerpzAuthServer,另一个是snowbox。
LerpzAuthServer这个例子是为了演示权威服务器,实现了角色之间的同步,聊天。此工程下有两个场景,可以理解为导出两个不同的exe程序。一个玩家登录后,会存在三个概念,ower,proxy,creator,分别代表自己,自己在其他玩家机器上的镜像,自己在服务器上的镜像。他们的区别在于,通过对应脚本的加减实现了不同的功能组合,ower支持操作控制,可以播放动画;creator不支持操作控制,也不播放动画;proxy是支持播放动画,但不支持操作控制。共同点在于,都有networkview脚本,
从场景结构上看,客户端与服务器的区别是两个GameObject节点,SpawnPoint和StartServer,前一个节点上挂了AuthSpawnPrefab脚本,此脚本重写了uLink_OnPlayerConnected方法,当一个玩家连接成功后,执行这个方法,这里执行的就是实例化玩家。这个过程在权威服务器上只能由服务器来做。StartServer节点上挂载了一个uLinkSimpleServer脚本,启动时会执行uLink.Network.InitializeServer方法初始化服务器,配置的参数是监听的端口号和最大的连接数。在socket初始化结束后,将调用uLink_OnServerInitialized方法。玩家断开连接后,将执行uLink_OnPlayerDisconnected方法,这里将执行对断开连接玩家的清理工作
uLink.Network.DestroyPlayerObjects(player);
uLink.Network.RemoveRPCs(player);
关于状态同步,即角色位置的同步,有两种情况,一种是玩家自身和服务器的位置同步,另一种是和玩家镜像的同步。
实例化出来的镜像ower,proxy,creator都会有一个脚本uLinkSmoothCharacter,其中调用了InvokeRepeating方法实现定期调用SendToServer这个方法,此方法将调用move的RPC方法,服务器执行这个move方法实现了服务器上角色位置的更新(权威服务器),实现了自己和服务器的状态同步。
该脚本里面重写了uLink_OnSerializeNetworkView方法实现了状态同步,主要同步了位置,速度,朝向三个变量。服务器将定时执行这个方法发送移动了的玩家位置等信息,代理对象收到这个信息后,移动代理的位置,从而实现了对所有代理对象(proxy)的资料更新。
snowbox工程,实现有客户端预测,插值,权威服务器,大厅服务器,玩家切换服务器等。
在角色的位移同步上,ower,proxy,creator上都挂了一个uLinkStrictPlatformer脚本,为了实现平滑的移动,此脚本里会对镜像的行为做修正和模拟,镜像会存储最近一组的玩家的位置,朝向等信息,通过这组信息进行插值计算当前镜像的位置。如果长时间没受到数据更新,镜像会根据最近一次镜像的状态数据模拟镜像的下一个位置和朝向。
服务器将模拟所有的物理行为包括重力,并检查角色是否有作弊行为。角色移动时将发送一个rpc,如果检测到玩家作弊,服务器会给客户端一个修正命令。如果玩家行为正常,就告知客户端,玩家行为正常。服务器收到角色位置,速度,旋转值,计算出一个位移值,并把玩家移动的位置存储起来,在lateupdate里,对玩家实际的目标点尝试进行修正。
关于仍雪球。当owner有鼠标点击行为后,将调用服务器的throw 这个RPC方法,告知服务器雪球的方向,服务器收到这个行为后,将实例化雪球并模拟仍雪球的行为,并广播给其他玩家。关于雪球实体,玩家触发雪球后,前后端都会实例化雪球,都挂载有Snowball脚本,利用胶囊体碰撞实现被击效果,区别是客户端(owner和Proxy)会挂一个TimedTrailRenderer这样的渲染相关的脚本来实现雪球拖尾的效果。这个意思就是,服务器上的gameobject可以不加载哪些不需要进行判定的行为。
关于切换服务器(非切场景)。支持creator切换到另外一个进程,由另外一个进程的服务器管理。uLink的P2P更多的是在服务器端的架构,不需要服务器端再维护一个中央服务器来协调各个服务器之间的资源(C/S模型)。uLink文档上说更多的是适用于服务器端的局域网直连。没看到说客户端在不同局域网之间的连接,所以默认它不具备打洞的功能。
建立P2P,给serverA 的一个gameobject上挂载一个uLinkNetworkP2P脚本,表示此server可以接受别的server的连接,给serverB上的一个GameObject上挂载一个uLinkNetworkP2PConnector脚本,同时将自动加上uLinkNetworkP2P脚本,他的逻辑是说,我要连接别人,那我也一定要能接受别人连我。服务器上执行的creator,在场景之间的切换,只需要调用一个HandoverPlayerObjects方法就可以。
uLink里有个uLobby的概念,游戏大厅,从功能上看处理用户的连接,然后找一台合适的服务器把玩家扔进去,支持P2P方式的连接,即玩家也可以开房间,让其他玩家加入,这样看起来暗黑3里也有这样的,比如开一个公共游戏,然后邀请别人加入进来,从一定意义上看就是网关。uLobby是运行在一个单独的U3D工程下,可以让其他的client连接。
uLink里的uZone,如下图:
这张图里有几个关键的概念
uZone Master是uZone network系统里的核心,当node连接到uZone network上之后,master将负责跟踪这些node信息,master也会管理uZone Client的连接。
上图里的node是个应用程序,保存node到master的session, 负责管理Instance,所谓Instance都可以认为是进程。node和node之间互相独立,node同时只能连接一个Master。一般情况,每台机器上只会有一个Node,一个uZone里会有多个Node。这里的Client很不一样,只有使用了uZone client api的才能称之为uZone client,这种client一般都是和uLobby合作的某种模式的服务器,当然也有别的,像负载均衡,分布式计算,分布式测试或者监控。
client请求master启动一个功能,master将会通知相应的node启动一个instance,也就是process(进程)。正常情况下一个instance就是一个进程。
关于Unity的网络框架的更多相关文章
- GJM : Unity3D 常用网络框架与实战解析 【笔记】
Unity常用网络框架与实战解析 1.Http协议 Http协议 存在TCP 之上 有时候 TLS\SSL 之上 默认端口80 https 默认端口 ...
- unity客户端基本框架(转载)
框架概述: 基础系统的框架搭建,其中包括: UI框架(NGUI + MVC) 消息管理(Advanced CSharp Messenger) 网络层框架(Socket + Protobuf ) 表格数 ...
- 事件驱动之Twsited异步网络框架
在这之前先了解下什么是事件驱动编程 传统的编程是如下线性模式的: 开始--->代码块A--->代码块B--->代码块C--->代码块D--->......--->结 ...
- Android网络框架源码分析一---Volley
转载自 http://www.jianshu.com/p/9e17727f31a1?utm_campaign=maleskine&utm_content=note&utm_medium ...
- 【从0到1】android网络框架的选型参考
项目会使用到 socket tcp 级的网络访问,想选取一个使用较成熟异步网络框架, 提到的网络框架: 1. volley, 2. xutils. 3. android 4. netty, 5. mi ...
- Twsited异步网络框架
Twisted是一个事件驱动的网络框架,其中包含了诸多功能,例如:网络协议.线程.数据库管理.网络操作.电子邮件等. Twisted介绍:http://blog.csdn.net/hanhuili/a ...
- Android中android-async-http开源网络框架的简单使用
android-async-http开源网络框架是专门针对Android在Apache的基础上构建的异步且基于回调的http client.所有的请求全在UI线程之外发生,而callback发生在创建 ...
- 深入mongoDB(1)--mongod的线程模型与网络框架
最近工作需要开始研究mongoDB,我准备从其源代码角度,对于mongod和mongos服务的架构.sharding策略. replicaset策略.数据同步容灾.索引等机制做一个本质性的了解.其代码 ...
- 结合Retrofit,RxJava,Okhttp,FastJson的网络框架RRO
Retrofit以其灵活的调用形式, 强大的扩展性著称. 随着RxAndroid的推出, Retrofit这样的可插拔式的网络框架因其可以灵活兼容各种数据解析器, 回调形式(主要还是RxJava啦)而 ...
随机推荐
- Linux学习心得之 linux命令
作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 前言 本篇博客是对 每日一linux命令(http://www.cnblogs.com/pe ...
- Google C++单元测试框架GoogleTest---GTest的Sample1和编写单元测试的步骤
如果你还没有搭建gtest框架,可以参考我之前的博客:http://www.cnblogs.com/jycboy/p/6001153.html.. 1.The first sample: sample ...
- Android Studio调试方法学习笔记
(注:本人所用Android Studio的Keymap已设为Eclipse copy) 1.设置断点 只有设置断点,才好定位要调试什么地方,否则找不到要调试的地方,无法调试.(调试过程中也可以增加断 ...
- Http相关知识
Http的无状态性 无状态是指,当浏览器发送请求给服务器的时候,服务器响应客户端的请求.但是当同一个浏览器再次发送请求给服务器的时候,服务器并不知道它就是刚才的浏览器.简单的说就是,服务器不会去记得你 ...
- MongoDB学习笔记~大叔框架实体更新支持N层嵌套~递归递归我爱你!
回到目录 递归递归我爱你!只要你想做,就一定能成功! 从一到二,从二到三,它是容易的,也是没什么可搞的,或者说,它是一种流水线的方式,而从三到十,从十到百,它注定要有一个质的突破,否则,它会把你累死, ...
- 【hadoop】如何向map和reduce脚本传递参数,加载文件和目录
本文主要讲解三个问题: 1 使用Java编写MapReduce程序时,如何向map.reduce函数传递参数. 2 使用Streaming编写MapReduce程序(C/C++ ...
- 关于Oracle报“ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务”错误
关于Oracle报“ORA-12514 TNS 监听程序当前无法识别连接描述符中请求服务”错误原因:listener.ora中没有指定监听服务器名. 如下是解决思路: 尝试1.通过重启服务的方式启动数 ...
- android 拔打电话功能
private void phoneCall(String num) { String phoneNum = "tel:" + num; Uri smsToUri = Uri.pa ...
- logback配置详解2<appender>
logback 常用配置详解(二) <appender> <appender>: <appender>是<configuration>的子节点,是负责写 ...
- Android应用源码基于安卓的个人隐私监控项目
本系统借鉴了现有安全软件的优点,设计了权限访问监控.流量监控.应用程序危险度监控和签名验证四个功能模块,同时针对现有安全软件的不足之处,对系统进行改进,让权限访问.流量监控.危险值等以图形化的方式呈现 ...