Unity多人游戏
终极目标
好了,现在要进行的是多人游戏方面的工作。
首先说第一个,终极目标。
终极目标是实现我们的项目的三个乘客和一个指挥员的联机运行。
状态机已经写好了,现在只需要连上网。
需要了解
开始了解unity联机原理。
需要了解的是:
一个网络管理员(器?)
一个玩家用来找到和加入游戏的用户图形界面
网络玩家预制体,玩家用来控制的
多人在线的脚本和物体
客户端服务器主机之间的关系
物体和动作的什么关系
网络管理员
- 有且只有一个
- 管理游戏状态
- 派生管理
- 场景管理
- 调试信息
- 匹配
- 定制
- 三种联网模式
- 客户端
- 服务器
- 同时作为服务器和客户端的主机
派生管理
一个代表玩家的预制体
将NetworkIdentity组件添加到玩家预制体上
一旦分配了一个玩家预制体就可以作为主机开始游戏
停止游戏会破坏玩家的预制体
要向网络管理员注册预制体
网络管理员通过newworkmanager.onserveraddplayer的方法生成玩家
起始位置
NetworkStartPosition确定玩家生成的位置
RoundRobin循环设置Startposition
GetStartPosition查找起始位置
场景管理
分为离线场景和在线场景
启动服务器或者主机将加载在线场景
在线场景名称存储在networkSceneName中
断开时可自动返回菜单场景
NetworkManager.ServerChangeScene() 可对所有连接的客户端更新场景
StartHost或者StopClient可能导致场景更改
场景更改会导致前一个场景被销毁
保证网络管理器设置为DontDestryOnLoad
也可以在不同场景单独设置网络管理器
定制
网络管理器HUD
运行时显示GUI
可以选择局域网模式和匹配模式两种
自己使用的时候要将Network Discovery 集成进去
匹配模式
创建
查找
向多人游戏服务发送请求
返回游戏当前存在的所有匹配项的列表
单击加入匹配就能加入
单人游戏转换为多人游戏
网络管理员的设置
添加NetworkManager
玩家预制体
创造预制体
在NetworkIdentity添加预制体
检查NetworkIdentity的LocalPlayerAuthority
将playerPrefabNetworkManager的“ Spawn Info”部分设置为玩家预制体
如果场景中存在玩家实例,则移除它
玩家动作
将NetworkTransform组件添加到玩家预制体
更新输入和控制脚本以遵守isLocalPlayer
修复相机来遵守派生的玩家和isLocalPlayer
游戏状态
将重要的数据放入NetworkBehaviours而不是Mono
将重要的成员放入SyncVars
联网动作
如上第一条
将执行重要玩家操作的功能更新为命令
非游戏玩家对象
添加NetworkIdentity
添加NetworkTransform
使用NetworkManager注册可派生预制体
使用游戏状态和操作更新脚本
派生
如上上第一条
派生器只放在服务器上使用(isServer属性或OnStartServer)
调用NetworkServer.Spawn()创建GameObjects
玩家的派生位置
添加一个新的物体放在玩家的起始位置
将NetworkStartPosition组件添加到新的物体
大厅
创建大厅场景
添加NetworkLobbyManager
配置大厅管理器
- 场景
- 预制体
- 派生器
调试
网络管理器HUD的Inspector上面有调试信息
- 网络连接
- 具有网络标志组件的活动的游戏物体
- 客户端上具有网络标志的游戏物体
- Client Peers不知道是啥
底部有消息回调句柄
高级API
不需要专用的服务器进程,和互联网服务一起工作。
命名空间unityEngine
- 消息处理程序
- 通用高性能序列化
- 分布式对象管理
- 状态同步
- 服务器客户端连接
服务器与主机
使用主机,本地服务端和服务器共享场景,本地直接函数调用和消息队列与服务器通信
实例化和生成
玩家和本地玩家
只能本地玩家物体上调用自己的网络命令
权限
服务器和客户端可以都对一个物体的动作进行管理
权限的概念是游戏对象是怎么和在哪被管理的
基于服务器权限作为默认的状态
玩家对象是有本地权限的特殊的情况
联网的游戏对象
只加入网络标志不够,还要加入那些属性应该同步
:cry:糟心了,有大概三节的内容丢失了,要重写。
- Network Transform 同步位置和旋转
- Network Animator 同步动画
玩家游戏对象
NetworkBehaviour类(您从中创建网络脚本)具有名为isLocalPlayer的属性。
在每个客户端的玩家GameObject上,Unity在NetworkBehaviour脚本上将该属性设置为true,并调用OnStartLocalPlayer()回调。
是否是本地玩家确定是否处理输入,是否使相机 跟踪或执行仅属于该客户端的玩家的任何其他客户端事物
玩家游戏对象能从玩家的客户端运行命令
其他非玩家服务器短游戏对象无法直接从客户端游戏对象接收到命令
Network Manager component 的 Inspector取消勾选Auto Create Player可以在一开始不创建自动生成玩家
自定义玩家派生
当网络管理器添加玩家时,它还会实例化一个游戏 Player Prefab 将其与连接关联。为此,网络管理器调用NetworkServer.AddPlayerForConnection。
可以通过重写NetworkManager.OnServerAddPlayer来修改此行为。默认实现OnServerAddPlayer从播放器Prefab实例化一个新的播放器实例,并调用NetworkServer.AddPlayerForConnection以生成新的播放器实例。
自定义实现OnServerAddPlayer必须调用NetworkServer.AddPlayerForConnection
NetworkServer.AddPlayerForConnection不一定要放在OnServerAddPlayer 里,只要传入正确的playerControllerId 就行
如果有多个玩家可以用playerControllerId 区分
系统会自动生成传递给NetworkServer.AddPlayerForConnection服务器的玩家GameObject ,因此无需为玩家调用NetworkServer.Spawn
一旦玩家准备就绪,游戏中的所有联网游戏对象都是在该客户端上以其最新状态创建的
准备状态
在客户端就绪之前可以
- 加载场景
- 选择角色
- 填写登录框
调用ClientScene.Ready进入“就绪”状态
NetworkServer.AddPlayerForConnection也会使客户端进入就绪状态
可以在没有游戏对象的情况下实现交互,有关在不使用命令和RPC调用的情况下发送消息的详细信息,请参阅网络消息文档。
切换玩家
NetworkServer.ReplacePlayerForConnection
从大厅切换到场景的时候不用摧毁原本的玩家,可以在加载好之后切换
如果连接的玩家GameObject被销毁,则该客户端无法执行命令。但是,他们仍然可以发送网络消息。
可以查找连接
派生游戏对象
派生意味着游戏对象是在服务器的客户端上创建的并由产生的系统管理
派生的游戏对象只要发生更改就会向客户端发送状态更新
这些派生的对象有唯一的ID netId
先要注册游戏预制体才能生成,注册的时候确定要有网络身份组件
注册:NetworkManager-SpawnInfo-Register……
没有网络管理器的派生:ClientScene.RegisterPrefab
约束
一个NetworkIdentity 必须位于可生成预制件体的根GameObject上。如果没有此,网络管理器无法注册预制件。
NetworkBehaviour 脚本 必须与NetworkIdentity在同一GameObject上,而不是在子GameObjects上
自定义派生函数
网络权限
服务器权限
服务器控制游戏对象
本地权限(客户端权限)
本地控制游戏对象
勾选 Local Player Authority
NetworkIdentity.hasAuthority 时候有本地权限
非玩家游戏对象本地权限
状态同步
SysncVars从服务器同步到客户端
可以在列表中的值改变的时候回调通知客户端
高级状态同步
不想看了
可见范围
场景游戏对象
Unity的多人游戏系统中有两种类型的联网游戏对象:
- 那些在运行时动态创建的
- 那些被保存为场景的一部分
在场景中保存联网的GameObjects(而不是在场景加载后动态生成它们)有一些好处:
- 它们加载了级别,因此在运行时不会暂停。
- 它们可以具有与预制件不同的特定修改
- 场景中的其他GameObject实例可以引用它们,这可以避免您必须使用代码来查找GameObject并在运行时引用它们。
行动和交流
远程操作
调用脚本
[Command]+函数名前面加Cmd,本地调用,服务器运行
可以添加信道
[ClientRpc]+函数名前面加Rpc,服务器调用,客户端运行
网络回调
网络消息
处理客户端和服务器
网络客户端和服务器
主机迁移
允许远程客户端之一成为新的主机
旧主机可能作为新主机上的客户端重新加入游戏
网络发现
只能用于局域网,不能用于互联网
多人游戏大厅
大厅玩家预制体
分配给大厅玩家预制体的必须要有网络大厅玩家组件
加入大厅的每一个客户端都会获得一个大厅玩家预制体创建的游戏对象
进入大厅调用OnClientEnterLobby
当游戏退出大厅时,Unity会在客户端上调用方法OnClientExitLobby。切换到游戏场景时会发生这种情况。
当该播放器的就绪状态发生变化时,Unity会在客户端上调用OnClientReady方法。
游戏玩家预制体
最小玩家数量
如果连接的客户端的数量达到最小玩家数量,那么等待所有连接的客户端变为就绪将启动匹配
使用传输层API
太高级不看
设置多人游戏
Windows->Servieces->Multiplayer
集成多人游戏服务
- 使用NetworkManagerHUD。(最简单,不需要脚本)
- 使用NetworkServer和NetworkClient。(高级,更简单的脚本)
- 直接使用NetworkTransport。(低级,更复杂的脚本)
使用HUD集成
- 创建一个新的空的游戏对象
- 添加NetworkManager和NetworkManagerHUD
- 创建预制体以代表玩家
- 添加NetworkIdentity 和NetworkTransform 给玩家
- 将玩家添加到网络管理器 检查器 ”的“ 播放器预制”属性,
使用高级API集成
使用NetTransport
常见错误
可能遇到的两个常见错误是:
Create match failed: Failed to access NetworkDB appId=0
如果您尚未将项目与Unity服务链接,则会发生这种情况。要将项目与Unity Services链接,请参阅为Unity Services设置项目。
Create match failed: Failed because of invalid projectid setup. Please verify project setup at https://multiplayer.unity3d.com
如果您尚未启用多人游戏服务,则会发生这种情况。要解决此问题,请确保已正确设置多人服务项目。
重写匹配回调
多人游戏组件
联网动画
- 如果GameObject在客户端上具有权限,则应在拥有GameObject的客户端上对其进行本地动画处理。该客户端将动画状态信息发送到服务器,服务器将其广播给所有其他客户端。例如,这适用于玩家角色。
- 如果GameObject在服务器上具有权限,那么您应该在服务器上为其设置动画。然后,服务器将状态信息发送给所有客户端。这对于与特定客户端无关的动画游戏对象(例如非玩家角色)很常见。
GetParameterAutoSend和SetParameterAutoSend函数可用于控制哪些个人动画参数应该被自动同步。
网络发现
本地使用
网络身份
网络大厅管理
网络大厅玩家
网络管理器HUD
网络接近检查器
网络开始位置
网络变形
网络子变形
网络变形可视化
多人游戏类参考
网络表现
如果已经读到这了可以不用看了……这水平直接看官网吧23333溜了