最近在尝试用unet做一个局域网游戏,游戏的核心概念在于玩家之间的发现和隐蔽,有个类似于战争迷雾的机制。

实现该机制最关键的是实现可视性检查。首先是unet中默认的一个可视性检查,由组件NetworkProximityChecker实现。其具体原理在 https://docs.unity3d.com/Manual/UNetVisibility.html 中有详细叙述,简单地说就是:

所有的networkIdentity都有一个观察者observer列表
在运行后的inspector下可以看到
值得注意的是,observer列表里保存的是player的gameobject。

这个observer列表表示,该物体被哪些networkConnection可见,对于不可见的networkConnection,server不会去做类似同步syncVar、或者调用clientRPC之类的操作。

按照文档的说法,这个observer列表会在两种情况下更新:

第一种情况:
在一个client被设置成ready之后,要对所有的network gameobject检查client能否看到它。该gameobject下的所有的networkBehaviour里的OnCheckObserver(NetworkConnection)会被调用,返回false表示该NetworkConnection看不到该gameobject。

第二种情况:
1.一个network gameobject在server上被spawn,要对所有的networkConnection检查能否看到该gameobject。
2.该gameobject中的,NetworkIdentity的RebuildObservers()方法被调用。需要重建Observers,该函数会调用同gameobject中的networkbehaviour中的onRebuildObservers
3.该方法签名如下
public override bool OnRebuildObservers(HashSet observers, bool initial);
实现者通过填充observers来表示哪些networkConnection对该gameobject可见。

注意两种方式的根本区别:第一种方式是一个新NetworkConnection进入后(client ready后),所有的network gameobject进行一次检查。第二种是一个network gameobject被创建后,所有的NetworkConnection做一次检查。

NetworkProximityChecker override了OnCheckObserver和OnRebuildObservers两个方法,通过检查距离实现检查。为了可见性能够刷新,同时在Update里定期调用NetworkIdentity的RebuildObservers方法。

以上是observer列表构建的一些事项。

之后,server会根据每个物体observers表的变化来对新增或者删除的networkConnection发送消息。比较麻烦的是在host上和client上的行为是不同的。

在client上,当一个物体可见性改变时,会收到来自服务器的消息。要注意的是,这个消息和在服务器上直接删除、创建物体时发送给客户端的消息是一模一样的。

而在host上,因为host本身的scene就是server的scene,不能直接把物体删除(不然就真没了)。因此需要另外实现行为。networkBehaviour提供了一个虚函数OnSetLocalVisibility(bool),这个函数只有在host上,失去或获得一个物体的可见性时被调用。在NetworkProximityChecker中实现的是把Renderer全部禁用或者启用,就实现了看不见的效果。不过因为UI的Canvas继承自Monobehaviour,消失时是不会被禁用的,如果要禁用的话需要自己实现一个component并且override OnSetLocalVisisbility。

最新文章

  1. AFNetworking 3.0 断点续传 使用记录
  2. 关于git中git pull --rebase中的一些坑
  3. Atitit机器学习原理与概论book attilax总结
  4. 10月16日上午MySQL数据库基础操作(创建、删除)
  5. BizTalk开发系列(三十六) Orchestration单实例执行
  6. mysql 插入中文报错: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect datetime value...
  7. UVA 10254 十八 The Priest Mathematician
  8. JS重写alert,保证弹窗错误的友好性
  9. int main(int argc,char* argv[]) 简单理解
  10. PHP 性能分析与实验(二)——PHP 性能的微观分析
  11. (转)PQ分区魔术师中文版分区教程
  12. DotNetNuke-DNN Module模块引用自定义CSS或者JS文件
  13. ibatis dynamic的用法
  14. JAVA基础——面向对象三大特性:封装、继承、多态
  15. jdk 1.8 开发环境配置
  16. MySQL多数据源笔记2-Spring多数据源一主多从读写分离(手写)
  17. Android性能优化典例(二)
  18. Lucene实现自己的英文空格小写分词器
  19. TSPL学习笔记(2):过程和变量绑定
  20. linux上的语音识别程序

热门文章

  1. Visual Studio Code 配置Go 开发环境最简单的方法!!!
  2. DFS(7)——poj1011Sticks
  3. UVA 437 The Tower of Babylon(DAG上的动态规划)
  4. .aspx文件和.aspx.cs文件的区别与联系
  5. laydate日期控件
  6. 当网卡收到的包的目的地址是主机上另一个网卡的地址.arp总结
  7. javaScript this 之谜
  8. hibernate多表查询
  9. 【bzoj1257】[CQOI2007]余数之和sum 数论
  10. 正式进军Matlab图像处理