Netcode网络框架与XRToolkit交互
笔记
记录下使用Unity网络框架的一些坑。最后实现一个简单的VR场景下的多人交互。
安装
从空白项目开始,2021.3版本。
包管理器安装com.unity.netcode.gameobjects
Transport
发现这个netcode.gameobjects
是依赖于Transport
的。后者就是一个基于UDP的连接库。
有一些官方给的例子可以参考。
netcode.gameobjects
照这个基础栗子。
该有的都有了。大致思路是
- 每个程序都拥有一套
NetworkManger
可在启动后选择是Sever还是Client。 NetworkManger
之间用Unity Transport
来连接。- 同时它还管理了
Player Perfab
的生成和销毁。对应的Player Perfab
需要有Network Object
组件来响应。 - 具体的逻辑要自己扩展
NetworkBehaviour
这个类,提供了基本的如生成和销毁时回调的函数。 - 服务器与客户端之间的相互调用用RPC来实现。
- 简单的传递数值之类的可以使用
NetworkVariable
来实现
太空侵略者Demo
又一个示例Demo,克隆下来看看。
SceneTransitionHandler
一个用来管理各个客户端场景切换和加载的NetworkBehaviour
。单例。简单的状态机,完成加载时通知服务器。
MenuControl
控制是开启Host或者当客户端加入。充当Server时会注册相关的场景加载完成的事件。
LobbyMenuControl
大厅用户以及状态管理,监听客户端连接,连接即当进入大厅。通过RPC相互之间更新状态。当全部准备完毕就加载游戏场景。
InvadersGame
最重要的游戏逻辑类。和网络关系就不大了。需要留意的是要生成的预制体要提前放入NetworkManager的NetworkPrefabs中,且预制体需要包含NetworkObject
组件。
如果要同步各个客户端的物体的位置,最便捷的方法就是使用NetworkTransform
,但这个是根据位移阙值去更新的,肯定会有至少一帧的延迟,如果是对精度要求很高的,还是用RPC自己调用来更新吧。
spaceshooter
针对物理给出的一个例子,所有的用户输入都通过RPC发送到服务器,然后统一计算后再发回全部客户端。和LOL的模式几乎一样,避免了物理的不同步,也防范了用户修改内存作弊等等。
clientdriven
在客户端实现部分运动逻辑,具体还没看。
XR toolkit联动
与XR toolkit 结合起来,做个多人VR交互的Demo吧。
延迟启动VR
参照这个官方的例子。
传送与交互
这里关于传送要注意,
InteractionManager
,locomotionSystem
等最好不要实例化,方便场景内的地板和传送点注册- 在生成后记得再把
locomotionSystem
需要的xrOrigin
和BaseTeleportationInteractable
需要的TeleportationProvider
一并补充了。
至于交互的物体,建议不要用物理。而且要通过实例化,并提前在NetworkManager中注册。
然后就是添加ClientNetworkTransform
。并在抓取对应物体时用ServerRpc
调用networkObject.ChangeOwnership
来改变所属关系。
同步
位置的同步可以用现成的 ClientNetworkTransform
其他,比如LineRenderer
的同步只能自己手写RPC了。
仿照NetworkTransform
这里就没有限制刷新次数。
防火墙
Server端不要忘了开防火墙。
人物绑定
都做到这一步了,干脆把人物的绑定也一并做了吧。
还是用Animation Rigging
。主要就是根据头显以及两个手柄推测出身体,头部,以及手臂和手的姿态。没用什么太复杂的算法。
- 身体头部单纯用头显位置和旋转去算。
- 手部只是用IK简单反推了一下。
我记得SteamVR是有对应的API去获取这些预测的位置的,但XRToolkit没有。
最终人物的手臂动画还有很大优化的空间,单单依靠IK去反推手臂姿态还是太牵强了,因为人的手腕也是很灵活的,而且肩膀的旋转也很难去推算出来,有这两个不确定的因素,除非用AI去算。很好奇VRChat是如何优化的。
总结
这个网络框架还是很好用的,符合Unity的习惯,迁移一些现有的逻辑到网络上也算比较方便了(和自己手撸Socket相比)。
与XRToolkit结合起来也不算复杂,能满足一些基本的交互逻辑了。