Unity用戶端架構筆記(狀態模式和策略模式在遊戲中的應用),unity用戶端

來源:互聯網
上載者:User

Unity用戶端架構筆記(狀態模式和策略模式在遊戲中的應用),unity用戶端

        最近花了幾天時間梳理了一下新遊戲的用戶端架構,雖然本身就有相對明確的方向,但是在一開始寫的時候還是有些混亂,不過最終梳理完成後,個人感覺代碼清爽很多。

        這篇文章不是設計模式的教學,而是自己的一些想法和實踐,我把代碼梳理成自己喜歡的結構,保證邏輯和結構的清晰,但是這並不意味者它是符合所有人習慣的。

        我之前有寫過一兩篇文章討論用戶端的結構,也吐槽過一些其他人的設計。可以說我在寫代碼之初就有一個相對明確的方向,多年的經驗也可以告訴我什麼樣的代碼是漂亮的,什麼樣的代碼是有壞味道的。

        首先我把用戶端結構分成三層,一層為顯示層Display,它處理遊戲最核心的戰鬥模組,如ARPG中的情境、角色、技能表現都是在這一層處理。一層為邏輯層Logic,它處理遊戲的各個系統,如資源管理、角色管理、任務管理等等都是放在這一層處理。一層為UI層,它就是由各個介面所組成的。

        各個層之間沒有嚴格的劃分,比如邏輯層內是各個單體管理器,顯示層也會有一個如Game或者BattleScene這樣的單體類,UI層會有一個UIManager來管理。但是如果各層相互穿插可能造成用戶端的混亂。所以做了一些界限的劃分。UI層可以調用邏輯層和顯示層的東西,各個介面之間不運行相互調用,而是通過事件來互動。邏輯層幾乎只處理邏輯,不調用另外兩個層的東西。 顯示層可以調用邏輯層的管理者來擷取資料或者與伺服器通訊。

        以上為大的架構或者思想,這個並不是很多人會提到的MVC架構,而是根據開發經驗總結出來的一套類似的東西。反正思想是一致的,那就是通過合理的層次劃分達到邏輯和顯示的分離,當一個地方修改的時候,不會影響到其他地方。這個就是“開閉原則”。雖然物件導向的一些原則非常教條,但是確實是代碼設計的指導方向。

        在架構確定的基礎上,還有一些細節的設計需要考量一下,基本上下面提到的一些問題都是各有優劣,所以我只作描述,不做選擇,具體看個人的習慣。

        1、是要一個全域公用的DataCenter來儲存資料,還是將資料分散到各個管理器內部?  使用公用的DataCenter來儲存資料,可以避免各個管理器之間的相互訪問,所有管理器都是從DataCenter來取資料,管理器之間通過事件來互動。但是不可避免的DataCenter會隨著時間的增長變得越來越龐大。  而管理器持有資料,則可能會造成各個管理者之間的相互訪問。如玩家要卸下身上裝備的武器,就要先從物品或者背包管理器裡面擷取背包剩餘空間,這樣兩個管理器就相互依賴了。

        2、訊息是每個訊息一個檔案來處理其自身邏輯,還是註冊一個id給對應的管理者來處理訊息資料? 

        3、是否要保持邏輯管理者之間的獨立性,以保證去掉某一個管理者,遊戲仍然可以編譯並運行?


        在上面這些結構問題梳理清楚後,就開始遊戲最核心的角色和戰鬥系統的設計了。這裡體現了開發人員抽象的能力,如果抽象能力很好,就可以一步到位,否則就要看重構的能力了。

        我的設計如下(請原諒我不會畫uml圖,就純口述了。。。):

        角色是一個繼承自MonoBehaviour的類,基類為Unit(也可以叫Actor或者Role),其下會有一些列的衍生類別如Player  NPC  Hero  Monster等等。  這些是最基本的角色。

        每個角色會持有一個data資料,如PlayerData   NPCData  HeroData等等,這些是邏輯層的東西,是純資料處理的,根據伺服器的訊息建立。如玩家的id,血量,攻擊力等等都是在這裡處理。

        Unit內部會管理一些列的Component,它們描述了某件事情該怎麼做,比如會有MoveComponent  AttackComponent  AnimationComponent   HUDComponent等等,這些Component會派生出一些列的子類,來具體實現一個行為,如AttackComponent可以有MeleeAttackComponent  RangeAttackComponet等等。 Player和Monster可以通過這些Component組合成自己想要實現的具體效果。而當實現需要修改的時候可以只關注Component內部,添加一個新的行為也僅僅是添加一個新的Component。同時Component是可以共用的,如Player和Hero很多Component是一樣的,但是HUDComponet不一樣,這個就是組合比繼承優越的地方。 這個設計模式就是策略模式。它通過封裝易變的演算法,達到從容應對變化的效果。

        與策略模式非常類似的是狀態模式。有一些時候它們之間的界限也並不是非常明確,某些套路既可以說成是一種策略,也可以說成是一種狀態。比如搜尋敵人,這個可以是一個行為,也可以是一個搜尋敵人的狀態(可以考慮分層狀態機器,這樣就可以一邊跑一邊搜尋敵人,狀態之間可以並行)。

         我這邊的處理是每個角色類會對應一些列的狀態實現,如Player有PlayerIdleState  PlayerMoveState  PlayerAttackState,而Monster有MonsterIdleState  MonsterMoveState,State可以有公用的基類如UnitMoveState,也可以沒有,這個就看Player和Monster之間狀態的相似度有多高,如果有大量重複的代碼的話,那麼就考慮有一個基類。

         狀態模式描述了一種狀態之間的流轉,比如進入Idle狀態應該做什麼,什麼時候要進入Move狀態,通過狀態劃分,可以保證角色在某一個時刻處於一個確定的狀態,而此狀態的邏輯處理都在該狀態類裡面完成。這樣就不會有各種混亂(比如在Update內部寫各種IsInState(xxxx)),達到解耦合的目的。同時狀態之間的流轉也可以清晰的表達出來,我們的邏輯也會清晰很多。狀態模式的具體實現就是有限狀態機器,它是實現AI非常重要的手段。

        總結一下我的實現就是 角色持有一些列的行為,以及一些列的狀態,通過行為描述具體做什麼,通過狀態原因怎麼做。這樣就可以把原本都寫在Player內部的代碼分散出來。而這個分散並不會使我們寫代碼更加麻煩,而是會讓我們的邏輯更加清晰,代碼更加容易閱讀。 如果沒有達到這樣的效果,而是感覺如果這些代碼都寫在Player內部可以更加方便的調用,那麼就一定是某個環節出了問題。

         我個人並不是很推崇設計模式,總是標榜自己是實用主義,但是回過頭來看的話,我們認為漂亮的設計很多時候就是一種模式。幾十個設計模式我們可能只熟悉其中最常用的幾個就受用無窮了。真正在開發中吃透這幾個模式,才可以真正瞭解物件導向、封裝,也才會瞭解什麼是漂亮的代碼,什麼是優雅的設計。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.