UNet详解(转)
Unity Networking(UNet)函數(shù)時(shí)序統(tǒng)計(jì)和分析
背景和概述
Unity Networking是官方自Unity5.1以來推出的新網(wǎng)絡(luò)通信解決方案。UNet是非官方但更民間更精簡的叫法。
本文需要讀者有基礎(chǔ)的UNet知識。
了解UNet時(shí)序,可以更好更嚴(yán)謹(jǐn)?shù)鼐帉慤Net相關(guān)的業(yè)務(wù)邏輯代碼。
本文針對UNet的HLAPI進(jìn)行時(shí)序統(tǒng)計(jì)和分析。
本文可作為工具文檔,需要時(shí)可進(jìn)行時(shí)序查閱。
在有時(shí)序統(tǒng)計(jì)的基礎(chǔ)上,本文再參考Unity Networking 5.3源代碼(Bitbucket網(wǎng)站可能需要翻墻)進(jìn)行整合分析,可以幫助了解底層發(fā)生的具體邏輯。
當(dāng)前將Unity(就算是Headless)運(yùn)行在Linux服務(wù)器上,會(huì)出現(xiàn)一定的性能問題。聯(lián)系咨詢過Unity內(nèi)部開發(fā)同學(xué)Ian和一位和藹大胖子,獲知Headless所剔除的功能模塊并不多,僅僅是最終不提交(也不能提交)到GPU、DSP而已。原話是“Modulization is hard”、“Should not run Unity on the server”。
所以當(dāng)前,應(yīng)避免粗暴地將Unity運(yùn)行在“關(guān)鍵”服務(wù)器上。
- 應(yīng)從業(yè)務(wù)層著手剔除Headless模式下所啟用的業(yè)務(wù)功能(如模型、渲染、物理、音效等)
- 將Unity運(yùn)行于“非關(guān)鍵”服務(wù)器(比如用于外掛分析,等)是可能可行的
- 將Unity無狀態(tài)地運(yùn)行,多“關(guān)鍵”服務(wù)器(比如用于戰(zhàn)斗)共享該Unity服務(wù)器,是有成功案例的
- 但粗暴地每一局游戲都在服務(wù)器運(yùn)行一個(gè)Unity進(jìn)程是欠妥的
可惜的是,UNet的默認(rèn)思路正是最后一種。由于Ian并非UNet Team的開發(fā)同學(xué),所以其并不十分了解將于Unity5.4(但被delay了)的Server Library所完成的功能。但一種推測是,Server Library正是為了避免將Unity運(yùn)行于服務(wù)器,而是提供UNet、Unity的基礎(chǔ)功能(Math等),讓我們服務(wù)器同學(xué)利用UNet接口,重新實(shí)現(xiàn)邏輯。
測試方法
測試Unity版本為5.3.1。運(yùn)行平臺(tái)是OSX。
測試NetworkManager通過NBNetworkManager繼承并override掉關(guān)鍵函數(shù);測試Player的Prefab名字為NBPlayer。通過在這個(gè)Prefab加上測試腳本TestNetworkBehaviour進(jìn)行日志輸出。
通過分析日志,可以統(tǒng)計(jì)UNet函數(shù)的時(shí)序。
函數(shù)時(shí)序概括
以下為關(guān)鍵函數(shù)的羅列,以供快速查詢之用。
如需可細(xì)看下一章節(jié)的詳細(xì)文檔及分析。
Dedicated Server情況
| Server初始化階段 | Server初始化階段 |
| Awake() | ? |
| Start() | ? |
| OnStartServer() | ? |
| ServerChangeScene() | ? |
| OnServerSceneChanged() | ? |
| Client初始化階段 | Client初始化階段 |
| OnServerConnect() | ? |
| OnServerReady() | ? |
| Player初始化階段 | Player初始化階段 |
| OnServerAddPlayer() | ? |
| ? | Awake() |
| ? | OnEnable() |
| ? | OnStartServer() |
| ? | OnRebuildObservers() |
| ? | OnSerialize()(多次) |
| ? | Start() |
| Player運(yùn)轉(zhuǎn)階段 | Player運(yùn)轉(zhuǎn)階段 |
| ? | FixedUpdate()(多次) |
| ? | Update()(多次) |
| ? | OnSerialize()(多次) |
| Player銷毀階段 | Player銷毀階段 |
| ? | OnDisable() |
| ? | OnDestroy() |
| OnServerDisconnect | ? |
| Server銷毀階段 | Server銷毀階段 |
| OnStopServer() | ? |
Remote Client情況
| Client初始化階段 | Client初始化階段 |
| Awake() | ? |
| Start() | ? |
| OnStartClient() | ? |
| OnClientConnect() | ? |
| OnClientSceneChanged() | ? |
| Player初始化階段 | Player初始化階段 |
| ? | Awake() |
| ? | OnEnable() |
| ? | OnDeserialize() |
| ? | PreStartClient() |
| ? | OnStartClient() |
| ? | OnStartLocalPlayer() |
| ? | OnStartAuthority() (后面運(yùn)轉(zhuǎn)階段也可能調(diào)到) |
| ? | OnDeserialize()(多次) |
| ? | Start() |
| Player運(yùn)轉(zhuǎn)階段 | Player運(yùn)轉(zhuǎn)階段 |
| ? | FixedUpdate()(多次) |
| ? | Update()(多次) |
| ? | OnDeserialize()(多次) |
| Player銷毀階段 | Player銷毀階段 |
| ? | OnNetworkDestroy() |
| ? | OnDisable() |
| ? | OnDestroy() |
| Client銷毀階段 | Client銷毀階段 |
| OnStopClient() | ? |
Host情況
| Host初始化階段 | Host初始化階段 |
| Awake() | ? |
| Start() | ? |
| OnStartHost() | ? |
| OnStartServer() | ? |
| ServerChangeScene() | ? |
| OnServerConnect() (LocalClient混雜進(jìn)來的Server函數(shù)) | ? |
| OnStartClient() (LocalClient混雜進(jìn)來的Client函數(shù)) | ? |
| OnClientConnect() (LocalClient混雜進(jìn)來的Client函數(shù)) | ? |
| OnServerSceneChanged() | ? |
| OnClientSceneChanged() (LocalClient混雜進(jìn)來的Client函數(shù)) | ? |
| OnServerReady() (LocalClient混雜進(jìn)來的Server函數(shù)) | ? |
| OnServerAddPlayer() (LocalClient混雜進(jìn)來的Server函數(shù)) | ? |
| OnServerConnect() | ? |
| OnServerReady() | ? |
| Player初始化階段 | Player初始化階段 |
| OnServerAddPlayer() | ? |
| ? | Awake() |
| ? | OnEnable() |
| ? | OnStartServer() |
| ? | PreStartClient() |
| ? | OnStartClient() |
| ? | OnRebuildObservers() |
| ? | OnSerialize()(多次) |
| ? | OnSetLocalVisibility() |
| ? | Start() |
| Player運(yùn)轉(zhuǎn)階段 | Player運(yùn)轉(zhuǎn)階段 |
| ? | FixedUpdate()(多次) |
| ? | Update()(多次) |
| ? | OnSerialize()(多次) |
| Player銷毀階段 | Player銷毀階段 |
| ? | OnNetworkDestroy() |
| ? | OnDisable() |
| ? | OnDestroy() |
| OnServerDisconnect | ? |
| Host銷毀階段 | Host銷毀階段 |
| OnStopHost() | ? |
| OnStopServer() | ? |
| ServerChangeScene() (LocalClient混雜進(jìn)來的Server函數(shù)) | ? |
| OnStopClient() (LocalClient混雜進(jìn)來的Client函數(shù)) | ? |
函數(shù)時(shí)序的詳細(xì)文檔及分析
以下為嚴(yán)格按照時(shí)間次序進(jìn)行羅列的UNet函數(shù)時(shí)序,附上官方文檔。重要地方也結(jié)合源碼進(jìn)行解釋。
Dedicated Server情況
Dedicated Server的Server初始化階段
NetworkManager.Awake()
NetworkManager目前的Awake()(被不好地設(shè)計(jì))為非virtual的私有方法。所以子類應(yīng)注意不能再定義Awake(),否則將hide掉基類的Awake()。
NetworkManager.Start()
NetworkManager (NewBorn.NBNetworkManager).Start()NetworkManager.OnStartServer()
public void OnStartServer();
Description
This hook is invoked when a server is started - including when a host is started.
StartServer has multiple signatures, but they all cause this hook to be called.
Server初始化函數(shù)。調(diào)用肯定比看似相似的OnStartClient()早。
注意在OnStartServer()之后,才進(jìn)行網(wǎng)絡(luò)Connect的初始化、才進(jìn)行場景的切換。
NetworkManager.ServerChangeScene()
public void ServerChangeScene(string newSceneName);
Parameters
newSceneName?The name of the scene to change to. The server will change scene immediately, and a message will be sent to connected clients to ask them to change scene also.
Description
This causes the server to switch scenes and sets the networkSceneName.
Clients that connect to this server will automatically switch to this scene. This is called autmatically if onlineScene or offlineScene are set, but it can be called from user code to switch scenes again while the game is in progress. This automatically sets clients to be not-ready. The clients must call NetworkClient.Ready() again to participate in the new scene.
StartServer()里、OnStartServer()之后,調(diào)用ServerChangeScene()進(jìn)行場景切換。之后在任意時(shí)刻,也可以手動(dòng)調(diào)用它進(jìn)行中途的場景切換。
在ServerChangeScene()里,會(huì)發(fā)出MsgType.Scene通知當(dāng)前已連接上的Client也進(jìn)行場景的切換。
Battle_Demo_Official
NetworkManager (NewBorn.NBNetworkManager).ServerChangeScene()
NetworkManager.OnServerSceneChanged()
public void OnServerSceneChanged(string sceneName);
Parameters
sceneName?The name of the new scene.
Description
Called on the server when a scene is completed loaded, when the scene load was initiated by the server with ServerChangeScene().
Server完成場景切換后的一個(gè)回調(diào)。
在本回調(diào)之前,Server會(huì)收集場景所有已有NetworkIdentity的GameObject,并發(fā)出Spawn的Message,從而通知已連接上的Client進(jìn)行Spawn。
Battle_Demo_Official
NetworkManager (NewBorn.NBNetworkManager).OnServerSceneChanged()
2016-01-01T10:57:28.8472060+08:00
至此,Server的初始化階段結(jié)束。之后(通過上面的時(shí)間10:57:28和下面的時(shí)間11:04:10就可以看出時(shí)間差),當(dāng)有Client連接進(jìn)Server的時(shí)候,函數(shù)流程就進(jìn)入該Client的初始化階段。
Dedicated Server的Client初始化階段
NetworkManager.OnServerConnect()
public void OnServerConnect(Networking.NetworkConnection conn);
Parameters
conn?Connection from client.
Description
Called on the server when a new client connects.
新玩家新Client和Server建立連接后的回調(diào)函數(shù)。
Client剛連接上來,第一個(gè)問題肯定是“我現(xiàn)在在什么場景?”。所以在本回調(diào)之前,Server會(huì)發(fā)出MsgType.Scene,通知客戶端進(jìn)行場景加載。
hostId: 0 connectionId: 1 isReady: False channel count: 2
NetworkManager (NewBorn.NBNetworkManager).OnServerConnect()
2016-01-01T11:04:10.7621350+08:00
NetworkManager.OnServerReady()
public void OnServerReady(Networking.NetworkConnection conn);
Parameters
conn?Connection from client.
Description
Called on the server when a client is ready.
The default implementation of this function calls NetworkServer.SetClientReady() to continue the network setup process
當(dāng)Client“準(zhǔn)備好”(加載好場景,一些自定義的初始化)后,需要發(fā)送MsgType.Ready給Server。
Server收到這個(gè)Message了之后,就會(huì)調(diào)用本OnServerReady()函數(shù)。
Client準(zhǔn)備好了之后,接著問題是“我Client當(dāng)前場景有什么網(wǎng)絡(luò)對象可見和需要同步?”
所以在OnServerReady()里會(huì)調(diào)用NetworkServer.SetClientReady(),進(jìn)行該Client的可見性檢測,然后在NetworkServer.SendSpawnMessage()里下發(fā)MsgType.ObjectSpawn進(jìn)行Spawn。
hostId: 0 connectionId: 1 isReady: False channel count: 2
NetworkManager (NewBorn.NBNetworkManager).OnServerReady()
至此,Client已經(jīng)連接好、加載好場景、同步好已有的網(wǎng)絡(luò)對象。
所以Server將進(jìn)入Player初始化階段。
Dedicated Server的Player初始化階段
NetworkManager.OnServerAddPlayer()
public void OnServerAddPlayer(Networking.NetworkConnection conn, short playerControllerId);
Parameters
conn?Connection from client.
playerControllerId?Id of the new player.
extraMessageReader?An extra message object passed for the new player.
Description
Called on the server when a client adds a new player with ClientScene.AddPlayer.
The default implementation for this function creates a new player object from the playerPrefab.
新連接上來的Client連接好了、場景準(zhǔn)備好了、其他有NetworkIdentity的GameObject同步好了,接下來準(zhǔn)備為該Client準(zhǔn)備屬于它自己的Player了。
通過調(diào)用ClientScene.AddPlayer()發(fā)出MsgType.AddPlayer可以通知服務(wù)器添加屬于該connection的Player,然后Server就響應(yīng)該Message會(huì)調(diào)用OnServerAddPlayer()。
用戶可以在OnServerAddPlayer()自定義新建Player的邏輯,包括直接Instantiate新Player、或者從自己的Spawn機(jī)制里取出Player、給Player修改初始化屬性等。
然后,在OnServerAddPlayer()里就會(huì)調(diào)用NetworkServer.AddPlayerForConnection(),繼而一系列初始化Player邏輯(生成netId、決定Observer、收集SyncVar、發(fā)送MsgType.Spawn給Client),通知Client真正去創(chuàng)建Player。
hostId: 0 connectionId: 1 isReady: True channel count: 2, 0
NetworkManager (NewBorn.NBNetworkManager).OnServerAddPlayer()
至此,Player的Prefab在Server已被Instantiate出來,繼而調(diào)用
- NetworkServer.AddPlayerForConnection()、
- NetworkServer.FinishPlayerForConnection()
- NetworkServer.SpawnObject()
等函數(shù),正式開始NetworkIdentity/NetworkBehaviour的函數(shù)流程。
NetworkBehaviour和NetworkIdentity是相互依存的。許多NetworkBehaviour的UNet相關(guān)函數(shù)事實(shí)上都是在其配對的NetworkIdentity中被NetworkIdentity所觸發(fā)調(diào)用的。
NetworkBehaviour.Awake()
留意到這次測試Player的GameObject的instanceID是-10746。
只有l(wèi)ocalPlayerAuthority=True
這個(gè)UNet配置變量是合法的。其他UNet變量都是非法的。
go.instanceID=-10746,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=0
playerControllerId=-1
connectionToClient=
connectionToServer=
isClient=False
isServer=False
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).Awake()
NetworkBehaviour.OnEnable()
go.instanceID=-10746,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=0
playerControllerId=-1
connectionToClient=
connectionToServer=
isClient=False
isServer=False
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).OnEnable()
NetworkBehaviour.OnStartServer()
public void OnStartServer();
Description
This hook is invoked when a server is started - including when a host is started.
StartServer has multiple signatures, but they all cause this hook to be called.
在NetworkIdentity.OnStartServer()里,
- 會(huì)cache住NetworkIdentity所同GameObject的所有NetworkBehaviour
- 會(huì)生成netId給自己
- 通過NetworkServer.instance.SetLocalObjectOnServer(),更新isServer的標(biāo)志位
- 調(diào)用這些NetworkBehaviour的OnStartServer()函數(shù)。
所以這個(gè)時(shí)候,netId和isServer合法了。
go.instanceID=-10746,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 2 isReady: True channel count: 2
connectionToServer=
isClient=False
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).OnStartServer()
NetworkBehaviour.OnRebuildObservers()
public bool OnRebuildObservers(HashSet<NetworkConnection> observers, bool initialize);
Parameters
observers?The new set of observers for this object.
initialize?True if the set of observers is being built for the first time.
Returns
bool?Return true if this function did work.
Description
Callback used by the visibility system to (re)construct the set of observers that can see this object.
Implementations of this callback should add network connections of players that can see this object to the observers set.
這個(gè)新的NetworkIdentity在Server創(chuàng)建了,但哪些Client是其真正的“觀察者”(Observer)呢?只有這些觀察者Client,才需要在他們的運(yùn)行時(shí)里創(chuàng)建這個(gè)新NetworkIdentity及其GameObject。
NetworkIdentity會(huì)調(diào)用其所有NetworkBehaviour的OnRebuildObservers()。
默認(rèn)情況下,是當(dāng)前已連接的所有Client都能觀察到這個(gè)新NetworkIdentity。
但如果有NetworkBehaviour的OnRebuildObservers()返回了true,則以HashSet<NetworkConnection> observers里存在的連接作為Observer。
observers=System.Collections.Generic.HashSet`1[UnityEngine.Networking.NetworkConnection], initialize=True,
go.instanceID=-10746,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 2 isReady: True channel count: 2
connectionToServer=
isClient=False
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).OnRebuildObservers()
NetworkBehaviour.OnSerialize()
public bool OnSerialize(Networking.NetworkWriter writer, bool initialState);
Parameters
writer?Writer to use to write to the stream.
initialState?If this is being called to send initial state.
Returns
bool?True if data was written.
Description
Virtual function to override to send custom serialization data.
決定了Observer后、給這些Observer發(fā)送MsgType.Spawn之前,需要在Server把這個(gè)新NetworkIdentity的GameObject的所有同步屬性進(jìn)行序列化。
OnSerialize()和OnDeserialize()
是用于自定義NetworkBehaviour中變量的序列化和反序列化的虛函數(shù)。前者必然是只在Server被調(diào)用、后者必然是只在Client被調(diào)用。
事實(shí)上,[SyncVar]修飾的變量和SyncList變量都是通過編譯時(shí)UNet將這些變量的序列化反序列化邏輯自動(dòng)生成在OnSerialize()和OnDeserialize()中的。
所以要注意,如果你在NetworkBehaviour中顯式override掉了這兩個(gè)函數(shù),則該NetworkBehaviour的[SyncVar]修飾的變量和SyncList變量都需要你自行編寫代碼實(shí)現(xiàn)序列化反序列化。
serializeCount=1, writer=UnityEngine.Networking.NetworkWriter, initialState=True,
go.instanceID=-10746,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 2 isReady: True channel count: 2
connectionToServer=
isClient=False
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).OnSerialize()
NetworkBehaviour.Start()
一幀真正開始。
go.instanceID=-10746,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 2 isReady: True channel count: 2
connectionToServer=
isClient=False
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).Start()
至此,在Dedicated Server的Player初始化階段已結(jié)束。接下來是Player運(yùn)轉(zhuǎn)階段。
Dedicated Server的Player運(yùn)轉(zhuǎn)階段
NetworkBehaviour.FixedUpdate()(多次)
fixedUpdateCount=22, go.instanceID=-10746,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 2 isReady: True channel count: 2
connectionToServer=
isClient=False
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).FixedUpdate()
NetworkBehaviour.Update()(多次)
updateCount=22, go.instanceID=-10746,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 2 isReady: True channel count: 2
connectionToServer=
isClient=False
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).Update()
NetworkBehaviour.OnSerialize()(多次)
serializeCount=16, writer=UnityEngine.Networking.NetworkWriter, initialState=False,
go.instanceID=-10746,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 2 isReady: True channel count: 2
connectionToServer=
isClient=False
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).OnSerialize()
Dedicated Server的Player銷毀階段
通過調(diào)用NetworkServer.Destroy(gameObject);,gameObject進(jìn)入銷毀階段。
NetworkBehaviour.OnDisable()
go.instanceID=-10746,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 2 isReady: True channel count: 2
connectionToServer=
isClient=False
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).OnDisable()
NetworkBehaviour.OnDestroy()
留意到所有變量皆已非法。
留意到在Server并不會(huì)調(diào)用OnNetworkDestroy()。
go.instanceID=-10746,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=0
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 2 isReady: True channel count: 2
connectionToServer=
isClient=False
isServer=False
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).OnDestroy()
至此,Player的NetworkIdentity/NetworkBehaviour流程結(jié)束。
NetworkManager.OnServerDisconnect()
public void OnServerDisconnect(Networking.NetworkConnection conn);
Parameters
conn?Connection from client.
Description?Called on the server when a client disconnects.
hostId: 0 connectionId: 2 isReady: False channel count: 2
NetworkManager (NewBorn.NBNetworkManager).OnServerDisconnect()
Dedicated Server的Server銷毀階段
略。因?yàn)樵赟erver kill掉Unity不能及時(shí)輸出日志。
至此,Player的整個(gè)Dedicated Server流程結(jié)束。
Remote Client情況
在上面已有Dedicated Server情況的前提下,Remote Client情況將適度從簡,僅針對差異性進(jìn)行描述。
Remote Client的Client初始化階段
NetworkManager.Awake()
NetworkManager目前的Awake()(被不好地設(shè)計(jì))為非virtual的私有方法。所以子類應(yīng)注意不能再定義Awake(),否則將hide掉基類的Awake()。
NetworkManager.Start()
NetworkManager (NewBorn.NBNetworkManager).Start()NetworkManager.OnStartClient()
public void OnStartClient(Networking.NetworkClient client);
Parameters
client?The NetworkClient object that was started.
Description
This is a hook that is invoked when the client is started.
StartClient has multiple signatures, but they all cause this hook to be called.
當(dāng)調(diào)用NetworkManager.StartClient()的時(shí)候,在其內(nèi)部進(jìn)行:
- Client注冊各種Client相關(guān)的MsgType監(jiān)聽(MsgType.Connect/Disconnect/Scene/)
- 連接,
- 然后會(huì)調(diào)用OnStartClient()。
UnityEngine.Networking.NetworkClient
NetworkManager (NewBorn.NBNetworkManager).OnStartClient()
Client連接成功后,第一個(gè)問題肯定是“我現(xiàn)在在什么場景?”。通過之前Dedicated Server情況的分析可知,Server會(huì)在Client連接成功后、OnServerConnect()之前通過MsgType.Scene通知客戶端切換場景。
所以此時(shí)之后,Client將進(jìn)行場景加載并成功。
BattleStarter.Awake()(場景中本就有的GameObject)
BattleStarter (NewBorn.BattleStarter).Awake()GlobalObject.OnLevelWasLoaded()(加載場景前就DontDestroyOnLoad的GameObject)
GlobalObject (MoreFun.GlobalObjectComponent).OnLevelWasLoaded()NetworkManager.OnClientConnect()
public void OnClientConnect(Networking.NetworkConnection conn);
Parameters
conn?Connection to the server.
Description
Called on the client when connected to a server.
The default implementation of this function sets the client as ready and adds a player.
當(dāng)場景加載成功后,才在NetworkManager.FinishLoadScene()里調(diào)用OnClientConnect()。
在OnClientConnect()里,當(dāng)沒有OnlineScene或當(dāng)前就是OnlineScene時(shí),就會(huì)立刻調(diào)用ClientScene.Ready()告訴Server本Client已準(zhǔn)備好。
所以此時(shí)的isReady是False。
hostId: 0 connectionId: 1 isReady: False channel count: 2
NetworkManager (NewBorn.NBNetworkManager).OnClientConnect()
NetworkManager.OnClientSceneChanged()
public void OnClientSceneChanged(Networking.NetworkConnection conn);
Parameters
conn?The network connection that the scene change message arrived on.
Description
Called on clients when a scene has completed loaded, when the scene load was initiated by the server.
Scene changes can cause player objects to be destroyed. The default implementation of OnClientSceneChanged in the NetworkManager is to add a player object for the connection if no player object exists.
當(dāng)場景加載成功后、調(diào)用OnClientConnect()后、在NetworkManager.FinishLoadScene()里繼續(xù)調(diào)用OnClientSceneChanged()。
OnClientSceneChanged()必然會(huì)調(diào)用ClientScene.Ready()告訴Server本Client已準(zhǔn)備好。所以根據(jù)之前的Dedicated Server情況分析可知,Server會(huì)在OnServerReady()里會(huì)調(diào)用NetworkServer.SetClientReady(),進(jìn)行該Client的可見性檢測、并進(jìn)行已在Server的NetworkIdentity的GameObject進(jìn)行反序列化和Spawn。
然后,如果NetworkManager配置成AutoCreatePlayer為true,則OnClientSceneChanged()還會(huì)在本Client找不到LocalPlayer時(shí)調(diào)用ClientScene.AddPlayer(0)通知Server生成本Client的玩家。
hostId: 0 connectionId: 1 isReady: False channel count: 2
NetworkManager (NewBorn.NBNetworkManager).OnClientSceneChanged()
其他Player的GameObject的其他腳本的Awake()
因此,其他Player就會(huì)比LocalPlayer先行在本Client被Spawn出來。
go.instanceID=-64522
NBPlayer(Clone) (NewBorn.PlayerController).Awake()
BattleStarter.OnStartClient()
本身就在場景里的有NetworkIdentity的GameObject也比LocalPlayer先行被Spawn出來。
至此,Remote Client的Client本身就初始化好了。
接下來,由于ClientScene.OnObjectSpawn()監(jiān)聽了MsgType.ObjectSpawn,所以當(dāng)Server生成本Client的LocalPlayer(或者Spawn其他任意GameObject時(shí)),本Client都會(huì)進(jìn)入NetworkIdentity/NetworkBehaviour的函數(shù)流程。
Remote Client的Player初始化階段
NetworkBehaviour.Awake()
只有l(wèi)ocalPlayerAuthority=True這個(gè)UNet配置變量是合法的。其他UNet變量都是非法的。
go.instanceID=-65642,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=0
playerControllerId=-1
connectionToClient=
connectionToServer=
isClient=False
isServer=False
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).Awake()
NetworkBehaviour.OnEnable()
go.instanceID=-65642,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=0
playerControllerId=-1
connectionToClient=
connectionToServer=
isClient=False
isServer=False
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).OnEnable()
NetworkBehaviour.OnDeserialize()
public void OnDeserialize([Networking.NetworkReader reader, bool initialState);
Parameters
reader?Reader to read from the stream.
initialState?True if being sent initial state.
Description
Virtual function to override to receive custom serialization data.
Server把這個(gè)新NetworkIdentity的GameObject的所有同步屬性進(jìn)行序列化會(huì)連同發(fā)送MsgType.Spawn一并下發(fā)。
所以Client接受Server的數(shù)據(jù)后也通過OnDeserialize()在本地進(jìn)行反序列化。留意到這是第一次反序列化initialState=True。
OnSerialize()和OnDeserialize()
是用于自定義NetworkBehaviour中變量的序列化和反序列化的虛函數(shù)。前者必然是只在Server被調(diào)用、后者必然是只在Client被調(diào)用。
事實(shí)上,[SyncVar]修飾的變量和SyncList變量都是通過編譯時(shí)UNet將這些變量的序列化反序列化邏輯自動(dòng)生成在OnSerialize()和OnDeserialize()中的。
所以要注意,如果你在NetworkBehaviour中顯式override掉了這兩個(gè)函數(shù),則該NetworkBehaviour的[SyncVar]修飾的變量和SyncList變量都需要你自行編寫代碼實(shí)現(xiàn)序列化反序列化。
deserializeCount=1, reader=NetBuf sz:87 pos:87, initialState=True,
go.instanceID=-65642,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=0
playerControllerId=-1
connectionToClient=
connectionToServer=
isClient=False
isServer=False
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).OnDeserialize()
NetworkBehaviour.PreStartClient()
public void PreStartClient();
Description
An internal method called on client objects to resolve GameObject references.
留意到經(jīng)過上一步的OnDeserialize()之后,合法變量為
- netId=7。
- isClient=True。
- isServer=False。
- gameObject.name已經(jīng)改變?yōu)楦鷖erver所給予的名字(NBPlayer7)。
- 事實(shí)上,所有SyncVar此時(shí)皆已合法。
go.instanceID=-65642,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=-1
connectionToClient=
connectionToServer=
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).PreStartClient()
NetworkBehaviour.OnStartClient()
public void OnStartClient();
Description
Called on every NetworkBehaviour when it is activated on a client.
Objects on the host have this function called, as there is a local client on the host. The values of SyncVars on object are guaranteed to be initialized correctly with the latest state from the server when this function is called on the client.
和PreStartClient()沒什么區(qū)別。當(dāng)然,SyncVar已經(jīng)合法。
go.instanceID=-65642,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=-1
connectionToClient=
connectionToServer=
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnStartClient()
NetworkBehaviour.OnStartLocalPlayer()
public void OnStartLocalPlayer();
Description
Called when the local player object has been set up.
This happens after OnStartClient(), as it is triggered by an ownership message from the server. This is an appropriate place to activate components or functionality that should only be active for the local player, such as cameras and input.
在一個(gè)Client運(yùn)行時(shí)中,只有一個(gè)Connection,有很多個(gè)Player。眾多Player中,只有和這個(gè)Connection綁定起來的Player,才“提拔為”LocalPlayer,代表的是本Client玩家的“MyPlayer”。所以,此時(shí)合法的變量就比較好理解了。
合法變量:
- playerControllerId=0
- connectionToServer=hostId: 0 connectionId: 1 isReady: True channel count: 2
- isLocalPlayer=True
Server發(fā)送MsgType.Owner給Client,然后Client就進(jìn)行LocalPlayer的更新。
注意,從源碼看來。LocalPlayer可以有多個(gè)。
另,應(yīng)注意,LocalPlayer的“Local”,和Host模式下的LocalClient的“Local”可不是同一個(gè)概念,應(yīng)分清區(qū)別:
- LocalClient的Local可理解為“同機(jī)器的”:是Host模式下,和Server同處于一部物理機(jī)器上的一種特殊的Client。LocalClient的并列相反概念是RemoteClient,RemoteClient是指和Server處于不同物理機(jī)器上的常見Client。
- LocalPlayer的Local可理解為“我自己的”,不管是RemoteClient,還是LocalClient,它們都會(huì)有本客戶端的自己的LocalPlayer。LocalPlayer的并列相反概念是DumbPlayer(作者本人喜歡的叫法),DumbPlayer是指本客戶端代表其他玩家的Player。
go.instanceID=-65642,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=
connectionToServer=hostId: 0 connectionId: 1 isReady: True channel count: 2
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=True
isLocalPlayer=True
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnStartLocalPlayer()
NetworkBehaviour.OnStartAuthority()
public void OnStartAuthority();
Description
This is invoked on behaviours that have authority, based on context and the LocalPlayerAuthority value on the NetworkIdentity.
This is called after OnStartServer and OnStartClient.When NetworkIdentity.AssignClientAuthority() is called on the server, this will be called on the client that owns the object. When an object is spawned with NetworkServer.SpawnWithClientAuthority(), this will be called on the client that owns the object.
當(dāng)一個(gè)NetworkIdentity配置有LocalPlayerAuthority時(shí),此NetworkIdentity認(rèn)為是可以授權(quán)給Client的。只有一個(gè)Client真正有Authority的時(shí)候,才可以在該GameObject的NetworkBehaviour中發(fā)送Command給Server。
什么時(shí)候Client才真正有Authority呢?LocalPlayer都是有Authority的。另自Unity5.2開始,也允許非Player在運(yùn)行時(shí)通過在Server調(diào)用NetworkIdentity.AssignClientAuthority()或NetworkServer.SpawnWithClientAuthority()將Authority賦予特定的Connection,即指定該Connection的Client也擁有該非Player的Authority,即允許該Client也可以在該非Player的NetworkBehaviour中發(fā)Command給Server。此時(shí)OnStartAuthority()這個(gè)函數(shù)是可以在那個(gè)時(shí)候再被調(diào)用到的。
Authority要么只有Server擁有,要么只有Client擁有。
合法變量:
- hasAuthority=True
go.instanceID=-65642,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=
connectionToServer=hostId: 0 connectionId: 1 isReady: True channel count: 2
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=True
isLocalPlayer=True
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnStartAuthority()
NetworkBehaviour.Start()
一幀真正開始。
go.instanceID=-65642,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=
connectionToServer=hostId: 0 connectionId: 1 isReady: True channel count: 2
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=True
isLocalPlayer=True
NBPlayer7 (MoreFun.TestNetworkBehaviour).Start()
至此,NetworkBehaviour的初始化階段已結(jié)束。接下來是正常運(yùn)轉(zhuǎn)階段。
Remote Client的Player運(yùn)轉(zhuǎn)階段
NetworkBehaviour.FixedUpdate()(多次)
fixedUpdateCount=15, go.instanceID=-65642,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=
connectionToServer=hostId: 0 connectionId: 1 isReady: True channel count: 2
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=True
isLocalPlayer=True
NBPlayer7 (MoreFun.TestNetworkBehaviour).FixedUpdate()
NetworkBehaviour.Update()(多次)
updateCount=4, go.instanceID=-65642,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=
connectionToServer=hostId: 0 connectionId: 1 isReady: True channel count: 2
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=True
isLocalPlayer=True
NBPlayer7 (MoreFun.TestNetworkBehaviour).Update()
NetworkBehaviour.OnDeserialize()(多次)
deserializeCount=5, reader=NetBuf sz:28 pos:28, initialState=False, go.instanceID=-65642,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=
connectionToServer=hostId: 0 connectionId: 1 isReady: True channel count: 2
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=True
isLocalPlayer=True
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnDeserialize()
Remote Client的Player銷毀階段
通過調(diào)用NetworkServer.Destroy(gameObject);,gameObject進(jìn)入銷毀階段。
NetworkBehaviour.OnNetworkDestroy()
public void OnNetworkDestroy();
Description
This is invoked on clients when the server has caused this object to be destroyed.
This can be used as a hook to invoke effects or do client specific cleanup.
留意只有客戶端才會(huì)被調(diào)用OnNetworkDestroy()。
go.instanceID=-65642,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=
connectionToServer=hostId: 0 connectionId: 1 isReady: True channel count: 2
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=True
isLocalPlayer=True
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnNetworkDestroy()
NetworkBehaviour.OnDisable()
go.instanceID=-65642,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=
connectionToServer=hostId: 0 connectionId: 1 isReady: True channel count: 2
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=True
isLocalPlayer=True
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnDisable()
NetworkBehaviour.OnDestroy()
go.instanceID=-65642,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=
connectionToServer=hostId: 0 connectionId: 1 isReady: True channel count: 2
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=True
isLocalPlayer=True
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnDestroy()
Remote Client的Client銷毀階段
通過點(diǎn)擊NetworkManagerHUD的Stop按鈕,停止Remote Client。
NetworkManager.OnStopHost()
public void OnStopHost();
Description
This hook is called when a host is stopped.
NetworkManagerHUD有bug。Remote Client情況點(diǎn)擊它也調(diào)用StopHost(),所以O(shè)nStopHost()也會(huì)被錯(cuò)誤地調(diào)用。
正式情況應(yīng)忽略。
NetworkManager.OnStopClient()
public void OnStopClient();
Description
This hook is called when a client is stopped.
在NetworkManager.StopClient()調(diào)用時(shí),先調(diào)用NetworkManager.OnStopClient(),然后再斷連接、清除GameObject、跳轉(zhuǎn)到OfflineScene。
NetworkManager (NewBorn.NBNetworkManager).OnStopClient()至此,Remote Client整個(gè)流程結(jié)束。
Host情況
在已有上面Dedicated Server、Remote Client的情況,Host情況也將適當(dāng)從略。
Host初始化階段
NetworkManager.Start()
NetworkManager (NewBorn.NBNetworkManager).Start()NetworkManager.StartHost()
public Networking.NetworkClient StartHost();
Returns
NetworkClient?The client object created - this is a "local client".
Description
This starts a network "host" - a server and client in the same application.
The client returned from StartHost() is a special "local" client that communicates to the in-process server using a message queue instead of the real network. But in almost all other cases, it can be treated as a normal client.
NetworkManager.OnStartHost()
NetworkManager (NewBorn.NBNetworkManager).OnStartHost()NetworkManager.OnStartServer()
NetworkManager (NewBorn.NBNetworkManager).OnStartServer()NetworkManager.ServerChangeScene()
Battle_Demo_Official
NetworkManager (NewBorn.NBNetworkManager).ServerChangeScene()
NetworkManager.OnServerConnect()(2次)(LocalClient混雜進(jìn)來的Server函數(shù))
hostId: -1 connectionId: 0 isReady: False channel count: 0
NetworkManager (NewBorn.NBNetworkManager).OnServerConnect()
NetworkManager.OnStartClient()(LocalClient混雜進(jìn)來的Client函數(shù))
UnityEngine.Networking.LocalClient
NetworkManager (NewBorn.NBNetworkManager).OnStartClient()
NetworkManager.OnClientConnect()(LocalClient混雜進(jìn)來的Client函數(shù))
hostId: -1 connectionId: 0 isReady: False channel count: 0
NetworkManager (NewBorn.NBNetworkManager).OnClientConnect()
NetworkManager.OnServerSceneChanged()
Battle_Demo_Official
NetworkManager (NewBorn.NBNetworkManager).OnServerSceneChanged()
NetworkManager.OnClientSceneChanged()(LocalClient混雜進(jìn)來的Client函數(shù))
hostId: -1 connectionId: 0 isReady: False channel count: 0
NetworkManager (NewBorn.NBNetworkManager).OnClientSceneChanged()
NetworkManager.OnServerReady()(LocalClient混雜進(jìn)來的Server函數(shù))
hostId: -1 connectionId: 0 isReady: False channel count: 0
NetworkManager (NewBorn.NBNetworkManager).OnServerReady()
NetworkManager.OnServerAddPlayer()(LocalClient混雜進(jìn)來的Server函數(shù))
hostId: -1 connectionId: 0 isReady: True channel count: 0, 0
NetworkManager (NewBorn.NBNetworkManager).OnServerAddPlayer()
至此,Host的Server初始化邏輯(混雜著LocalClient的初始化邏輯)結(jié)束。
進(jìn)入Player初始化階段。
Host情況的Player初始化階段
NetworkManager.OnServerConnect()
hostId: 0 connectionId: 1 isReady: False channel count: 2
NetworkManager (NewBorn.NBNetworkManager).OnServerConnect()
NetworkManager.OnServerReady()
hostId: 0 connectionId: 1 isReady: False channel count: 2
NetworkManager (NewBorn.NBNetworkManager).OnServerReady()
NetworkManager.OnServerAddPlayer()
hostId: 0 connectionId: 1 isReady: True channel count: 2, 0
NetworkManager (NewBorn.NBNetworkManager).OnServerAddPlayer()
至此,開始Player的Prefab在Host已被Instantiate出來。正式開始NetworkIdentity/NetworkBehaviour的函數(shù)流程。
NetworkBehaviour.Awake()
go.instanceID=-78256,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=0
playerControllerId=-1
connectionToClient=
connectionToServer=
isClient=False
isServer=False
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).Awake()
NetworkBehaviour.OnEnable()
go.instanceID=-78256,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=0
playerControllerId=-1
connectionToClient=
connectionToServer=
isClient=False
isServer=False
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).OnEnable()
NetworkBehaviour.OnStartServer()
合法變量:
- netId=2。由于是Host,所以不需調(diào)用OnDeserialize()。立刻確定了netId。
- isServer=True
go.instanceID=-78256,go=NBPlayer(Clone) (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=False
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer(Clone) (MoreFun.TestNetworkBehaviour).OnStartServer()
NetworkBehaviour.PreStartClient()
go.instanceID=-78256,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=True
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).PreStartClient()
NetworkBehaviour.OnStartClient()
go.instanceID=-78256,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=True
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnStartClient()
NetworkBehaviour.OnRebuildObservers()
observers=System.Collections.Generic.HashSet`1[UnityEngine.Networking.NetworkConnection], initialize=True,
go.instanceID=-78256,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=True
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnRebuildObservers()
NetworkBehaviour.OnSerialize()(多次)
serializeCount=1, writer=UnityEngine.Networking.NetworkWriter, initialState=True, go.instanceID=-78256,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=True
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnSerialize()
NetworkBehaviour.OnSetLocalVisibility()
public void OnSetLocalVisibility(bool vis);
Parameters
vis?New visibility state.
Description
Callback used by the visibility system for objects on a host.
Objects on a host (with a local client) cannot be disabled or destroyed when they are not visibile to the local client. So this function is called to allow custom code to hide these objects. A typical implementation will disable renderer components on the object. This is only called on local clients on a host.
vis=True, go.instanceID=-78256,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=True
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnSetLocalVisibility()
NetworkBehaviour.Start()
go.instanceID=-78256,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=True
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).Start()
至此,Host情況的NetworkIdentity/NetworkBehaviour的初始化階段已結(jié)束。接下來是正常運(yùn)轉(zhuǎn)階段。
Host情況的Player運(yùn)轉(zhuǎn)階段
NetworkBehaviour.FixedUpdate()(多次)
fixedUpdateCount=5,
go.instanceID=-78256,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=True
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).FixedUpdate()
NetworkBehaviour.Update()(多次)
updateCount=4,
go.instanceID=-78256,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=True
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).Update()
NetworkBehaviour.OnSerialize()(多次)
serializeCount=4, writer=UnityEngine.Networking.NetworkWriter, initialState=False, go.instanceID=-78256,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=True
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnSerialize()
Host情況的Player銷毀階段
通過調(diào)用NetworkServer.Destroy(gameObject);,gameObject進(jìn)入銷毀階段。
NetworkBehaviour.OnNetworkDestroy()
go.instanceID=-78256,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=True
isServer=True
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnNetworkDestroy()
NetworkBehaviour.OnDisable()
go.instanceID=-78256,go=NBPlayer7 (UnityEngine.GameObject)
netId=7
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnDisable()
NetworkBehaviour.OnDestroy()
go.instanceID=-78256,go=NBPlayer7 (UnityEngine.GameObject)
netId=0
playerControllerId=0
connectionToClient=hostId: 0 connectionId: 1 isReady: True channel count: 2
connectionToServer=
isClient=True
isServer=False
localPlayerAuthority=True
hasAuthority=False
isLocalPlayer=False
NBPlayer7 (MoreFun.TestNetworkBehaviour).OnDestroy()
NetworkManager.OnServerDisconnect()
hostId: 0 connectionId: 1 isReady: False channel count: 2
NetworkManager (NewBorn.NBNetworkManager).OnServerDisconnect()
至此,Host情況的Player流程結(jié)束。
Host銷毀流程
NetworkManager.OnStopHost()
NetworkManager (NewBorn.NBNetworkManager).OnStopHost()NetworkManager.OnStopServer()
NetworkManager (NewBorn.NBNetworkManager).OnStopServer()NetworkManager.ServerChangeScene()
BattleOffline
NetworkManager (NewBorn.NBNetworkManager).ServerChangeScene()
NetworkManager.OnStopClient()
NetworkManager (NewBorn.NBNetworkManager).OnStopClient()至此,Host情況全部流程結(jié)束。
轉(zhuǎn)自http://www.jianshu.com/p/63bb685a36d6
總結(jié)
- 上一篇: 表达式类型出错
- 下一篇: socket网络编程udp