汽車之家Unity前端通用架構(gòu)升級實踐
背景介紹
隨著之家3D虛擬化需求的增加,各產(chǎn)品線使用Unity引擎的項目也越來越多,新老項目共存,代碼維護(hù)成本也隨之增加。代碼質(zhì)量參差加之代碼規(guī)范仍沒有完全統(tǒng)一產(chǎn)生高昂學(xué)習(xí)成本進(jìn)一步加重了項目維護(hù)負(fù)擔(dān)。
為應(yīng)對這些問題,我們決定借助主機廠數(shù)科產(chǎn)品線銷冠神器VR版本大升級為契機,開發(fā)一套移動端通用Unity代碼框架,旨在統(tǒng)一Unity項目開發(fā)流程和規(guī)范,使不同項目開發(fā)人員能夠快速上手業(yè)務(wù)開發(fā),實現(xiàn)不同項目之間代碼組件化復(fù)用,降低學(xué)習(xí)成本,提高項目的健壯性和復(fù)用性。
1.Unity 架構(gòu)調(diào)研
Unity通用架構(gòu)核心想幫助Unity開發(fā)人員加速項目開發(fā)效率。該架構(gòu)的設(shè)計基于大量的經(jīng)驗和最佳實踐,旨在使項目開發(fā)更加高效和規(guī)范化。通過使用通用架構(gòu),開發(fā)人員可以輕松地構(gòu)建高質(zhì)量、健壯和可擴(kuò)展的項目,同時降低學(xué)習(xí)成本和維護(hù)成本。該架構(gòu)的模塊化設(shè)計也允許不同的項目之間實現(xiàn)組件復(fù)用,從而進(jìn)一步提高開發(fā)效率。無論是初學(xué)者還是經(jīng)驗豐富的開發(fā)人員,使用Unity通用架構(gòu)都可以獲得更好的開發(fā)體驗。
1.1Unity與其他技術(shù)棧差異
與其他平臺相比,Unity的技術(shù)生態(tài)相對較為有限,缺少許多開源項目的支持。此外,Unity項目的類型繁多,從重度MMRPG項目到輕度虛擬仿真,這本身就是整理出一套通用的基礎(chǔ)架構(gòu)十分困難的原因之一。與此同時,大多數(shù)基礎(chǔ)功能都需要收費,而大型公司也很少開源他們的源代碼。因此,與其他平臺相比,Unity想要整理出一套通用前端技術(shù)框架確實面臨著很多挑戰(zhàn)。
1.2業(yè)界常用開源Unity框架
下面分析一下市面上常見的Unity架構(gòu),并列舉不適合我們的原因。
?UnityGameFramework
UnityGameFramework使用一套UnityFramework和一套Gameframework對Unity進(jìn)行了一次封裝。
在封裝的基礎(chǔ)上做了一些方便開發(fā)者使用的擴(kuò)展,如ECS/UI等功能。


?QFramework
QFramework 是提供一套簡單、強大、易上手、符合 SOLID 原則、支持領(lǐng)域驅(qū)動設(shè)計(DDD)、事件驅(qū)動、數(shù)據(jù)驅(qū)動、分層、MVC 、CQRS、模塊化、易擴(kuò)展的架構(gòu)。

1.3場景適用性思考
以上兩個架構(gòu)已足夠優(yōu)秀,但是要集成到我們的技術(shù)棧中還是有很多挑戰(zhàn):
?UnityGameFramework
這套架構(gòu)太“重”了,使用A模塊必須依賴架構(gòu)內(nèi)的B模塊甚至C/D/E模塊,只想使用簡單的UI功能可能要把整套架構(gòu)都遷移進(jìn)來。
太“重”也引起了修改一個模塊會牽連很多其他模塊的問題。
適合需求明確的中重度游戲,商業(yè)化項目。
?QFramework
學(xué)習(xí)成本較高,需要理解很多設(shè)計原則才可以上手使用。
它與UnityGameFramework相比又太“輕”了,源碼少,可魔改的余地少。適合小而精的項目。
?其他
其他架構(gòu)都缺少線上足夠項目實際驗證與配套的開源生態(tài),健壯性與擴(kuò)展性無法確保。
1.4架構(gòu)關(guān)注點思考
好的架構(gòu)應(yīng)該注重以下幾個方面:
?生命周期
良好的生命周期設(shè)計,可以提供簡單而高效的生命周期管理機制使開發(fā)人員在合適的時機創(chuàng)建、修改和銷毀對象。
生命周期感興趣的同學(xué)可以深入了解一下Unity的MonoBehavior設(shè)計。
?分層設(shè)計
分層設(shè)計可以使代碼解耦,將參考后端多種架構(gòu)設(shè)計理念,MVC、DDD、洋蔥架構(gòu)等,免代碼耦合,為提高架構(gòu)防腐度,降低續(xù)的化和重構(gòu)提的頻率。
?學(xué)習(xí)成本
考慮到員工技能水平的參差不齊,學(xué)習(xí)成本是設(shè)計架構(gòu)時最需要考慮的因素之一。,果架構(gòu)過于“重”,那么就需要了解很多底層/中間層邏輯才能使用,且出現(xiàn)問題后也不易于修改。
?上線驗證
如果一套架構(gòu)已經(jīng)通過多個項目的上線驗證,那么就不太需要擔(dān)心架構(gòu)中還有未解決的問題。開源架構(gòu)都會列出自己的產(chǎn)品案例。
2.之家Unity架構(gòu)設(shè)計
綜合上述總結(jié),在設(shè)計Unity通用架構(gòu)時重點考慮了分層設(shè)計,好的分層邊界能降低學(xué)習(xí)成本提高復(fù)用性。
2.1分層設(shè)計
汽車之家Unity通用架構(gòu)采用四層設(shè)計:邏輯層、中間層、基礎(chǔ)層和數(shù)據(jù)層。
?邏輯層
邏輯層處理不同項目的交互邏輯,調(diào)用中間層和基礎(chǔ)層功能。在邏輯層中,可以按照項目需求進(jìn)行設(shè)計,而不需要考慮復(fù)用性。
具體模型和數(shù)據(jù)功能通過調(diào)用底基礎(chǔ)層和數(shù)據(jù)層接口現(xiàn)。
?中間層
中間層對邏輯層和基礎(chǔ)層進(jìn)行封裝,使得邏輯層調(diào)用更加清晰,基礎(chǔ)層有更好的抽象環(huán)境。
中間層又分為業(yè)務(wù)層和適配器層。業(yè)務(wù)層主要針對邏輯層進(jìn)行封裝和特殊處理,而適配器層則對基礎(chǔ)層進(jìn)行二次封裝,組合多個基礎(chǔ)層能力以應(yīng)對復(fù)雜功能。
?基礎(chǔ)層
基礎(chǔ)層對基礎(chǔ)功能進(jìn)行抽象,使用統(tǒng)一的接口設(shè)計,支持所有Unity項目。這一層可以使用市面上普及的解決方案如TMP/DoTween等。
基礎(chǔ)層應(yīng)對功能抽象,不關(guān)心具體需求,具有良好的健壯性和可擴(kuò)展性。
?數(shù)據(jù)層
數(shù)據(jù)層用于后臺存儲、數(shù)據(jù)和模型信息等。只要使用同樣的后臺服務(wù)和美術(shù)規(guī)范,新的Unity項目就不需要對數(shù)據(jù)層再做兼容。
如有特殊需求,也可以在中間層對數(shù)據(jù)層進(jìn)行處理,參考洋蔥架構(gòu)設(shè)計。
2.2架構(gòu)圖
以下是汽車之家Unity通用架構(gòu)的架構(gòu)設(shè)計圖與銷冠神器使用通用架構(gòu)后的架構(gòu)圖:
?Unity通用架構(gòu)圖

?銷冠神器架構(gòu)圖

2.3代碼示例
以原生端通信功能為例,說明分層和復(fù)用性設(shè)計在架構(gòu)中的體現(xiàn)。
這里ativeMessage是一個可以與原生端進(jìn)行通信的模塊。該模塊負(fù)責(zé)向iOS和Android平臺發(fā)送和接收消息,用于處理一些原生交互的邏輯。
基礎(chǔ)層的NativeMessage在Plugin文件夾中,只有核心的發(fā)送消息和接受消息的能力

中間層的XGNativeMessage在Scripts/Manager文件夾中,繼承基礎(chǔ)層并添加業(yè)務(wù)相關(guān)的設(shè)置。


邏輯層在Module或Controller中對中間層的XGNativeMessage進(jìn)行調(diào)用

大致流程如下:

?優(yōu)勢總結(jié):
這種設(shè)計可以確?;A(chǔ)層有100%的復(fù)用性,使其可以方便地將其遷移至其他項目中使用。此外,中間層的封裝可以集中處理發(fā)送消息的邏輯,從而避免在邏輯層中編寫大量代碼。
采用分層設(shè)計的具有很方便的升級和擴(kuò)展性。如果需要對其中某一層進(jìn)行升級,可以直接修改對應(yīng)層級的代碼,而不會影響其他層的功能。這使得系統(tǒng)更加靈活和可維護(hù)。
分層設(shè)計和復(fù)用性是非常重要的架構(gòu)設(shè)計原則。在NativeMessage模塊的設(shè)計中,成功應(yīng)用了這些原則,使得該模塊具有高度的可復(fù)用性和可維護(hù)性。
3.架構(gòu)收益
通用架構(gòu)1.0上線后,我們量化了架構(gòu)收益:
?代碼質(zhì)量 升20%
底層和中間層按照功能解耦,可以提高代碼質(zhì)量,也降低單個迭代SP的bug率20%以上。
?開發(fā)效率 升30%
按照相同的框架發(fā)可規(guī)范,高開單人力研發(fā)需求交付效率30%以上同時,不同項目組之間可以共享同一套底層功能,從而互相幫助和提高生產(chǎn)力。
代碼規(guī)范和模塊拆分的方式符合Unity行業(yè)的通用解決方案,這可以幫助Unity開發(fā)人員更快地理解和掌握項目的架構(gòu)設(shè)計和開發(fā)規(guī)范。
?各項性能指標(biāo)提升20%
通過架構(gòu)升級,不僅解耦了代碼,還帶來了其他收益。例如,將GLB升級為AssetBundle,可以顯著降低內(nèi)存占用量,并減少CPU負(fù)載30%以上。
功能模塊化設(shè)計使得我們可以更好地統(tǒng)計啟動時各個階段所占用的時間,并針對下載/加載等階段進(jìn)行優(yōu)化,從而使啟動時間降低了50%。
這些優(yōu)化措施可以進(jìn)一步提高應(yīng)用程序的性能和用戶體驗,提高產(chǎn)品的競爭力。
?跨項目代碼復(fù)用度提升50%
通用架構(gòu)需要支持之家的所有Unity項目,所以需要考慮不同項目中的代碼復(fù)用。代碼復(fù)用性可以根據(jù)分層由低到高來考慮,最底層的代碼復(fù)用性越高。
邏輯層復(fù)用率0%,因為每個項目的交互邏輯不同,過多考慮復(fù)用會引起很多問題。這一層不需要考慮復(fù)用性的設(shè)計。
中間層復(fù)用率60%,中間層對邏輯層和基礎(chǔ)層進(jìn)行抽象和二次封裝,應(yīng)該在開發(fā)過程中盡量考慮復(fù)用性。至少適配器層要能快速地復(fù)用到其他項目中。
基礎(chǔ)層復(fù)用率100%,基礎(chǔ)層抽象基礎(chǔ)功能,只考慮功能而不關(guān)心業(yè)務(wù)。
數(shù)據(jù)層復(fù)用率100%,數(shù)據(jù)層由后端提供,使用相同的服務(wù)和美術(shù)規(guī)范。
4.總結(jié)
分層設(shè)計降低了上手成本,只要邏輯層足夠清晰簡單,那么初級程序員就可以很容易的去寫一些業(yè)務(wù)相關(guān)的功能,有能力的程序員可以持續(xù)為架構(gòu)輸出健壯的中間層和底層能力。邏輯層只采用最簡單的狀態(tài)機設(shè)計,如果之后業(yè)務(wù)需求復(fù)雜也可以擴(kuò)展成分層狀態(tài)機來實現(xiàn)復(fù)雜的業(yè)務(wù)需求。
5.經(jīng)驗分享
架構(gòu)設(shè)計應(yīng)該注重分層設(shè)計與上手成本,當(dāng)這兩點設(shè)計較好時,像易用性,復(fù)用性,解耦等優(yōu)點就會自然出現(xiàn)。
分層設(shè)計可以讓業(yè)務(wù)代碼不會侵入功能代碼,而學(xué)上手本低也會帶來易維護(hù),提效等好處。
6.引用
分享一下本文所引用的架構(gòu)鏈接:
UnityGameFramework:
https://github.com/EllanJiang/UnityGameFramework
QFramework:
https://github.com/liangxiegame/QFramework
本文使用ChatGPT幫忙檢查語法和拼寫錯誤,并提供優(yōu)化建議以提高文章的流暢性和可讀性。
作者簡介

胡春源
■ 主機廠事業(yè)部-創(chuàng)新項目團(tuán)隊
■ 2022年2月入職汽車之家,先后負(fù)責(zé)VI銷冠神器和全息倉的架構(gòu),優(yōu)化,功能開發(fā)等工作?,F(xiàn)在主要負(fù)責(zé)Unity項目的架構(gòu)和功能的相關(guān)工作。















 
 
 













 
 
 
 