@import url(http://www.shnenglu.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
來源:http://cl314413.blog.163.com/blog/static/1905079762012102124637521/
https://blog.51cto.com/kenkao/1707619
前言:
本簡易文檔主要翻譯自Photon官方Mmo文檔,也加入了一些自己的理解和提示,以后會嘗試著用自己的項目來講一講具體的開發流程。當然。。水平問題,肯定會有我不知道的錯誤,建議對照著英文原版來看。(雖然這貨耽誤了我兩個月時間,但還是想說好值啊!)不多廢話了,直接開始。
一、基礎:興趣管理(Interest Management)
玩游戲都知道,作為一個在線游戲來講,人物的走動是基礎中的基礎。然而,在虛擬世界中,一個東西位置發生變化會觸發位置更新消息。為了在其他客戶端展示這個東西是在流暢的運動,最少需要每秒10次的更新。
但問題在于,如果這個游戲是成百上千人在玩的話。。。作為客戶端來講肯定不能讓它接受到所有人物移動的消息的,計算機會爆掉。。所以呢,興趣管理就是解決這個問題的好方法了。每個客戶端都只獲取他想要的事件,也就是他所能看見的東西的事件。

二、概念
游戲中的虛擬世界(IWorld)有一個建立在坐標基礎上的虛擬空間。
每個坐標都是被3D向量表現出來的。幾個坐標定義了一個區域(IArea)。
每一個在這個虛擬世界中存在的物體都被叫做“物品”(Item)。
客戶端用位置和范圍定義他們感興趣的區域,并且只能看到這個興趣區域(Interest Area)范圍內的物品。

思路來了,但是呢,計算哪些物品進入哪些興趣區域會非常消耗CPU資源,尤其當物品和興趣區域在快速的運動的時候。
一個加快這個計算過程的簡單方法就是把虛擬空間劃分成一些固定地帶(fixed Regions)然后只計算哪些地帶和興趣區域是重疊的。
客戶端會接收到所有重疊地帶中的事件。
而這,就是傳說中的貼圖算法了(Square Tile Algorithm)。

一旦一個物品出現在了特定的興趣區域的邊界之內,這個興趣區域就會自動的把客戶端實例(peer)和這個物品的事件頻道(event channel)相訂閱。
客戶端從這一刻起就會收到所有被這個物品或者通過它發送的消息。
如果一個物品是在興趣區域的邊界來回晃悠的話,很可能就會造成頻繁的訂閱和未訂閱的變化。為了解決這個問題,一個附加的更大的興趣范圍(interest area radius)就這么被創造出來了。已訂閱的物體如果出了這個范圍那就不再被訂閱,客戶端也就不再接收它的事件。

三、Photon MMO 功能
1、基于地帶(region)的興趣管理
使用貼圖算法,長度和寬度可變,并且平鋪尺寸也已經實現好了(tile size is implemented)
很方便用其他的地帶算法取代默認的貼圖算法。
2、物品(角色,NPC,共享的游戲對象)【Items(Avatars,NPCs,shared game objects)】
客戶端可以產生、銷毀或者移動物品。
物品具有可以被其他客戶端讀取以及被所有者更改的屬性。
物品屬性里有一個修訂號碼(revision number),客戶端如果在一定時間內看不到一個物體了,可以把修訂號碼進行比較,以此決定接不接受該物品屬性的更新。
3、興趣區域:物品的事件在興趣區域中是被自動接收的
興趣領域有兩個興趣界點(interestthresholds)。物品進入里面的興趣區域邊界(inner radius)會變的可視,離開外面的興趣范圍就會變得不可視。這會最優的減少頻繁的可視狀態變化。

1 不可視物品,范圍之外
2 不可視物品進入外圍興趣區域
3 不可視物品進入內部興趣區域變得可視了
4 可視物品離開內部興趣區域
5 可視物品離開外圍興趣區域變得不可視了
興趣區域可以被重新設置范圍大小:調整視野范圍以適應能看見的物品的數量
為了提高在擁擠區域內的程序性能
在物品比較稀少的區域可以展示較遠的物品。
興趣區域可以附加給任何物品:無論是在物品移動了興趣區域之后還是改變了興趣區域本身。這對本身的角色移動興趣區域尤其有用。(Whenever the item moves the interest area follows and changes theinterest accordingly. This is especially useful to move the interest area withthe own avatar.)
已分離的興趣區域可以被自由的移動,這對攝像機漫游很有幫助。
客戶端可以有多個興趣區域在同一時間展示世界的不同部分。
4、自動的興趣管理
客戶端可以自動的申請或者取消掉物品的興趣區域。(Clients can manually (un-)declare interest in items.)
5、自定義事件(Custom events)可以通過物品發送到兩個可能的目標
物品的擁有者所有對物品感興趣的客戶端
6、最優化的位置更新機制:客戶端只會在物品移動的時候才會發送更新消息。
7、復制用戶的確認信息:發生在后的用戶連接會重置之前的連接信息。(Duplicate user recognition: A subsequent user connection resets theprevious con-nection.)
四、狀態機(StateMachine)
一個客戶端實例peer有如下的狀態。
1、 Connected:在連接之后的初始狀態,玩家還沒有進入世界。
2、 WorldEntered:在向服務端發出EnterWorld的請求以后,玩家進入世界。
3、 Disconnected:客戶端未連接。

Peer實例為每一個狀態使用一個不同的申請句柄(operation handler)。這允許申請在每個狀態下表現的不同。下面是用到的申請句柄。
-
State Connected: Photon.MmoDemo.Server.MmoPeer
-
State WorldEntered: Photon.MmoDemo.Server.MmoActor
-
State Disconnected: Photon.SocketServer.Rpc.OperationHandlerDisconnected
客戶端應該在呼叫一個狀態變化申請之后一直等待與之關聯的申請返回或者事件(operation response / event)。客戶端實例peer的狀態和現在的申請句柄【operationhandler (operation behavior)】在沒有接收到返回或者事件是不會被確認的。EnterWorld申請將會返回一個申請返回,ExitWorld申請將會返回一個事件WorldExited。
五、白楊的話
1、整個的MMO項目(包括客戶端和服務端)就在photon服務端SDK的src-server文件夾下。右鍵sln解決方案,用VS2010打開就可以看到了。

我第一次看的時候一下子就懵了。。這忒復雜了吧,都什么啊。。。
但是后來慢慢探索就明白各個項目的關系了。
簡單的來說,Client.DotNet的項目內容和Client.Unity3D等同。是客戶端例子的基礎,已經封裝好了peer初始化、operation申請、興趣區域等基礎類。這兩個項目編譯出來以后都是一個單獨的類庫,是后面那三個client例子用的。Client例子的任務就是引用基礎類庫,開發更加圖形化的功能,比如Radar(物品雷達,用來管理地圖上的物品,畫小地圖)。
MmoDemo.Common和MmoDemo.Server都是服務端的內容。Common定義了幾個用來傳送事件的ID或Code枚舉。而Server就主要是用來實現服務端邏輯了。
2、如何用這貨來開發MMO功能呢?
舉例來說,如何開發一個簡單的登陸注冊功能?
大概思路如下:(這里只是簡述,肯定不完整,我會爭取在我的項目比較穩定以后用項目來說明)
1) 在client基礎類庫項目的GameStateStrategies中加入一個新狀態類Login.cs。
2) 在項目的Operations.cs中實現入一個新的傳送用戶名和密碼的方法,注意,這里你使用的OperationCode服務端還無法識別,先記下。過程中別忘了新狀態。
3) 在你要更改的例子中,在enterworld之前調用這一方法。
4) 來到服務端的common,在OperationCode.cs之中定義好你剛才在客戶端中傳送的OperationCode,還要分別在ErrorCode和EventCode中給這個登錄方法加一個申請返回和事件回復的Code。
5) 再來到server,在Operations中加入判斷登錄信息的新類,在Events中加入返回成功失敗消息的新類。過程中還是別忘了判斷Login狀態。
3、 至于用什么數據庫。。。能力有限,一直用的都是LINQ To SQL,架設比較方便,在photon中使用也很簡單,這方面的技術查閱C#紅皮書或者新出的數據庫技術的書就好。不過目測這貨已經過時了,所以。。也不是太敢確定會一直用它,慢慢來,比起各種缺文檔的photon,數據庫好學多了不是么!