携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情
Unity Scene中的Game Objects
非网络游戏对象和网络游戏对象
开发游戏时,我们会在Scene中放置很多游戏对象,这其中有一部分是非网络游戏对象,如障碍物,装饰物等,这些物体的状态不会改变或者其状态改变不需要让其他玩家了解,因此不需要进行网络同步,只要正常添加到场景中就可以。另外有一些在场景中放置的游戏对象,需要和玩家进行交互,因此需要进行网络同步,让所有玩家都能得到其改变后的状态,比如可破坏物品,当一个玩家去攻击它,其他玩家也能看到其被击毁。这类游戏对象显然属于网络游戏对象。让一个场景中的游戏对象成为网络游戏对象,必须要在它上面添加NetworkIdentity组件,另外根据需要同步的属性,添加相应的同步组件以及自定义网络脚本。
场景网络游戏对象和动态创建的网络游戏对象
上面提到的场景网络游戏对象是预先放置在场景中的,而另一类网络游戏对象是通过Spawning System动态创建的。动态创建的网络游戏对象需要在Network Manager中注册用于实例化他们的prefab。而场景中预先放置的网络游戏对象则不需要注册prefab,其实他们可能不一定有prefab,因为他们是随着场景载入的,不需要动态创建。即便这类游戏对象有prefab,放置到场景后也可以任意override。
场景网络游戏对象的载入和激活
场景网络游戏对象作为场景中的一部分随着场景载入,在任何玩家连接上之前,他们就已经存在于服务器的场景中。当场景载入时,所有的场景网络游戏对象会在服务器和客户端场景中被禁用(deactive),场景载入全部完成后,Network Manager会自动处理场景中所有的预置网络游戏对象,将它们全部注册到Network Manager中统一管理,并且激活它们。看上去这些对象是在场景载入后实时生成的。当然实际的激活,需要有玩家连接上,在Host模式下,Host client是立即连入自己的server的,因此你会看到进入游戏时,这些网络游戏对象出现了。当客户端连接时,对于所有服务器场景中存在的且对客户端可见的场景网络游戏对象,客户端会收到ObjectSpawnScene消息。这个消息会使得客户端上的相应的游戏对象被激活,并且会具有服务器上对象的状态。也就是说如果一个客户端在游戏中途加入,他会看到当前的游戏状态,一些物体已经被摧毁的不会看到,一些部分损坏的可以看到部分损坏的状态。
使用场景预制网络游戏对象的好处
- 随场景载入,更方便策划编辑关卡,因为如果是动态载入,策划只能放置一些出生点,而不是对象本身。并且由于是已经和场景一起载入,不需要游戏运行时动态的加载。
- 更方便编辑,不限于使用prefab
- 可以在场景中被其他对象引用,因为他们是静态放置好的。如果是动态生成的对象,需要使用代码找到他们并设置引用。
场景网络游戏对象的使用
场景中的网络游戏对象被激活后,其行为和动态生成的网络游戏对象就一样了。Mirror正常的同步他们,以及调用RPC。
Tank项目中测试
场景中放置网络游戏物体
Tank场景中并没有预先放置网络游戏物体,我们可以先放置一个。如下图,创建一个Cube,并添加NetworkIdentity组件:
运行游戏,此时服务器未启动
我们发现,Cube对象被自动隐藏了
点击Host按钮,服务器启动,本机客户端自动连入
可以看到,Cube对象出现了。而旁边的坦克对象,则是动态生成的网络游戏对象。
补充
这个场景中的地面,是非网络游戏对象,所以一开始就出现了。 这个例子比较简单,只有一个场景,且没有根据游戏的状态,是否启动服务器去切换场景,所以能看到Cube对象在启动Host之后突然出现的过程。而在一个正常的联网游戏中,在启动服务器之前是一个独立的场景,比如是一个游戏大厅或房间,启动服务器之后载入游戏所需要的场景,由于场景是切换的,你只会看到新场景出现,且新场景中有Cube这样的对象存在,你并不会意识到Cube是进入后才激活的,它看上去就和地面一样是同场景一起出现的。