捕魚開發日誌

最近在用Laya3d做捕魚,版本是2.x,語言爲ts, unity版本爲5.6.x最新,底層架構準備使用puremvc singleton版本,js quardtree,然後再自己寫個2d碰撞引擎,還有其它邊腳料的東西,暫時不述

----2019-08-30 10:40:29-----

-------------------------------------

有些感慨,因爲要離職了,三個月的早十晚十,沒想到換來的是這種結果,呼呼。

經過三個月的奮鬥,捕魚遊戲己經全部完成,大部分BUG也都己修復,乘着離職前的空閒,繼續寫完這篇博文吧。

關於庫:

quardtree並沒有用上,因爲碰撞引擎的效率還是蠻高的,4個玩家40發子射撞擊100條以內的魚,穩定60幀。

關於設計:

遊戲在整體上分了三層,分別爲網絡層、數據邏輯層、表現層,數據邏輯層由Service和DB兩個模塊組成,表現層則使用了puremvc框架來實現,隨便給張手稿意思下:

網絡層:實現心跳,斷線重連,服務器重定向,協議封包解包,消息廣播等功能

數據層:持有所有遊戲邏輯數據,包括由服務端同步過來的玩家數據,魚數據,子彈數據,技能狀態,小遊戲狀態,服務端時間及網絡延時,由表現層傳過來的子彈與魚的碰撞盒信息,以及客戶端設置等等。

邏輯層:由3個Service來實現對所有遊戲業務的支持,其中:

1. MainService支持用戶的登陸登出,大廳的房間選擇,遊戲的進入和退出等功能。

2. PhysicsService實現遊戲中子彈及技能與魚的碰撞計算,以及魚的路徑與子彈的軌跡計算,同時基於需求,它還負責驅動表現層中的漁場及所有3D模型的鏡像翻轉和最終位置計算

3. FisheryService專門負責同步服務端與客戶端表現層中的漁場狀態和玩家操作,包括同步玩家、炮臺和子彈信息,同步魚的路線與狀態,同步技能與小遊戲狀態,上行碰撞信息,處理擊殺業務和抽獎業務等等。

表現層:這一層中所實現的功能則與玩家所看到的密切相關,基本的數據模型包括:房間數據,玩家集,子彈集,魚集,碰撞映射集,小遊戲狀態等等,組件則包括金幣及獲得播報,魚模型及特殊魚播報,獎勵播報,擊殺播報及特效,各種技能模型和各種小遊戲播報和場景或組件,就不一一敘述了。

在這個架構中,表現層與邏輯層是完全分離的,兩層之間的交互完全通過Command與Message來實現,表現層只派發Command,邏輯層只派發Message,故Command只處理View和Model中的數據,Message只處理DB中的數據,若表現層需要向底層或網絡寫入數據,則應當由Command派發Message消息來間接更新,反之邏輯層也只能以在Message中派發Command的方式來與表現層進行間接交互。

關於實現:

似乎並沒有太多可以說的點。就說下碰撞解決方案,漁場鏡像的設計和魚的穿插問題吧。

1. 碰撞解決方案:給魚加AB盒,A爲球體且僅爲一個,B爲球體或長方體且可能有多個,子彈爲2D對象,碰撞的實現爲每幀都將魚的A盒轉化成2D圓型,然後與子彈進行碰撞,或未相撞,則跳過,若相撞,則計算所有B盒的2D數據,然後逐一與子彈進行精確碰撞計算。

2. 鏡像設計,這個來源於一個在3-4號玩家眼中,要求看自己和12號一樣是處於漁場下方,而12號玩家則處於自己對面的需求

前置條件:魚處於XZ平面

解決思路:當PhysicsService計算完魚的路線之後,通知表現層計算鏡像信息,計算方式爲,若玩家爲3-4號,則所有魚的Z取反,角度在6點爲0度的前提下根據Z軸取負,魚的鏡像位置確立;由於魚又有上中下三層的分層,故攝像機的位置,也要繞Z軸進行旋轉,否則的話,比如下圖中的點A的鏡像位置,會與非鏡像位置有偏差,散遊的魚身上可能體現不明顯,魚陣出現時可就能明顯看出魚陣整體上移了。

3. 魚的穿插問題,由於漁場在設計中爲一個長16米,寬7.2米,高3.6米的長方體,策劃在編輯魚線路的時候,大魚在上層,中魚在中層,小魚在下層,由於不同分層中的魚都相互處於同一高度,故游泳時會出現穿插的情況

如上圖中,左邊長方體爲漁場的範圍,大魚123穿模,解決思路將魚在視錐上以不同的深度進行排列,間距與魚的A盒直徑有關。

那些踩過的坑:

Laya2.0的坑:

1. 這可能也不能算是Laya的坑,但它這樣設計,總覺得有點讓人鬱悶,Laya2.0中的所有prefab和scene,包括龍骨,3D模型,似乎在引擎中都是以模版的型式存在,當你調用對象的destroy,實際上銷燬的只是克降的對象,而非模版數據,這樣帶來的一個問題就是,如果你使用的骨骼動畫,或場景中的資源佔的內存比較大,或你遊戲素材展開後所佔的內存比較大時,安卓還好,蘋果直接閃退了,哪個你勾選了場景的autoDestroyAtClosed也是沒用的,autoDestroyAtClosed,其實調的destroy接口,也只是對象的接口,引擎並沒有提供釋放模版數據的接口,這不得不讓我覺得這是一個坑,因爲我得自己寫資源管理器啊。

可能有人說laya提供了gc和lock功能,我只想說,這兩個接口弱爆了,因爲你沒法爲不想gc的數據做計數統計,當我兩個預置用了同一張資源時,想在遊戲中做動態加載和釋放,光憑這兩個接口是不可能的,好吧,只能自己實現一個Resource管理器了,在這裏貼一下接口吧

    /**
     * 資源管理器
     */
    namespace Resource {

        /**
         * 根據url創建對象
         * @method: 創建失敗時res爲null,僅支持Skeleton和Texture的創建
         * @flag: 目前僅用於代替aniMode的值
         * 說明:
         * 1. 調用此接口創建對象時,會產生一個計數,當計數爲0時,資源會被徹底釋放
         * 2. 見destroy方法
         */
        function create(url: string, method?: (res: any, url: string) => void, caller?: Object, flag?: number): any;

        /**
         * 銷燬對象
         * 說明:
         * 1. 見create方法
         * 2. 調用此接口銷燬對象時,會移除一個計數,當計數爲0時,當計數爲0時,資源會被徹底釋放
         * 3. 若存在有部分邏輯未使用此接口加載資源,卻調用此接口銷燬資源,則可能會導致該資源被卸載或不可用,請注意
         */
        function destroy(url: string, method?: (res: any, url: string) => void, caller?: Object): void;

        /**
         * 資源預加載
         * @method: 預加載完成時,ok爲true,id大於0,僅支持Skeleton和Texture
         * @return: 返回資源組ID
         */
        function prepare(urls: string[], method: (ok: boolean, id: number) => void, caller: Object): number;

        /**
         * 釋放資源組
         * @id: 資源組ID
         * @return: 始終返回0
         */
        function release(id: number): number;
    }

因爲3D資源比較小,而且項目很趕,所以並沒有考慮3D資源的加載和釋放,所有3D資源統一在遊戲啓動時加載,加上所有公用圖集,合100M左右

若要使用大圖或龍骨,則可以通過create方法來創建,若未曾加載,則此接口會先加載,用完後調用destroy來釋放資源,此操作會產生計數,當所有對象都destroy掉後,龍骨或圖片對應的位置資源也會徹底釋放。

場景中的龍骨和大圖,若始終存在的,則建議在加載場景之前先加載,若像炮臺這種不存在的,則使用create和destroy動態創建和銷燬,防止可惡的佔坑不拉S。

至於prefab中的龍骨和大圖,則可以在創建prefab之前先加載,若prefab中用了多個大圖或龍骨,則建議先調用prepare來對所有資源進行預加載,然後銷燬時再對該組資源進行釋放,防止窗口出現但背景或龍骨沒出現的情況。

emmmmmm,原本遊戲啓動時加載所有資源,總共460M,實現自己的資源管理器之後,GPUMemory在遊戲啓動後120M,大廳130M,遊戲內135M,峯值160不到,+40M GPUMemory剛好200M,完美。

最後說下感慨,其實一直以來都很想進軍3D遊戲,無奈面試時總是因爲答不出造核彈的核心而被刷,其實能有這次機會來做3D捕魚對我來說是非常幸運的,這是我做的第一個3D項目,雖然是短短的三個月,但足以讓我摸索了很多的技術細節,實踐了很多曾經想做但卻沒有機會做的東西,當然也還有很多想法,很多想好的優化思路都沒有時間去實施,可能站在產品的角度,三個月太長了,但對我來說,三個月太短了,且憑心而論尤其是對於一個精品遊戲,三個月的時間,出來的真的只是一個模子而己,真的還有很多可以調優的地方,回想起這三個月,前期我催人,後期人催我,可能這就是客戶端的無奈吧,只能說我無愧於自己,己經成功地在計劃內與客戶正式對接的時期之前交付了一個穩定的版本。

再見,本以爲能實現很多理想的地方。

----2019-12-12 14:17:55-----

-------------------------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章