汽車之家Unity前端通用架構(gòu)升級(jí)實(shí)踐
背景介紹
隨著之家3D虛擬化需求的增加,各產(chǎn)品線使用Unity引擎的項(xiàng)目也越來越多,新老項(xiàng)目共存,代碼維護(hù)成本也隨之增加。代碼質(zhì)量參差加之代碼規(guī)范仍沒有完全統(tǒng)一產(chǎn)生高昂學(xué)習(xí)成本進(jìn)一步加重了項(xiàng)目維護(hù)負(fù)擔(dān)。
為應(yīng)對(duì)這些問題,我們決定借助主機(jī)廠數(shù)科產(chǎn)品線銷冠神器VR版本大升級(jí)為契機(jī),開發(fā)一套移動(dòng)端通用Unity代碼框架,旨在統(tǒng)一Unity項(xiàng)目開發(fā)流程和規(guī)范,使不同項(xiàng)目開發(fā)人員能夠快速上手業(yè)務(wù)開發(fā),實(shí)現(xiàn)不同項(xiàng)目之間代碼組件化復(fù)用,降低學(xué)習(xí)成本,提高項(xiàng)目的健壯性和復(fù)用性。
1.Unity 架構(gòu)調(diào)研
Unity通用架構(gòu)核心想幫助Unity開發(fā)人員加速項(xiàng)目開發(fā)效率。該架構(gòu)的設(shè)計(jì)基于大量的經(jīng)驗(yàn)和最佳實(shí)踐,旨在使項(xiàng)目開發(fā)更加高效和規(guī)范化。通過使用通用架構(gòu),開發(fā)人員可以輕松地構(gòu)建高質(zhì)量、健壯和可擴(kuò)展的項(xiàng)目,同時(shí)降低學(xué)習(xí)成本和維護(hù)成本。該架構(gòu)的模塊化設(shè)計(jì)也允許不同的項(xiàng)目之間實(shí)現(xiàn)組件復(fù)用,從而進(jìn)一步提高開發(fā)效率。無論是初學(xué)者還是經(jīng)驗(yàn)豐富的開發(fā)人員,使用Unity通用架構(gòu)都可以獲得更好的開發(fā)體驗(yàn)。
1.1Unity與其他技術(shù)棧差異
與其他平臺(tái)相比,Unity的技術(shù)生態(tài)相對(duì)較為有限,缺少許多開源項(xiàng)目的支持。此外,Unity項(xiàng)目的類型繁多,從重度MMRPG項(xiàng)目到輕度虛擬仿真,這本身就是整理出一套通用的基礎(chǔ)架構(gòu)十分困難的原因之一。與此同時(shí),大多數(shù)基礎(chǔ)功能都需要收費(fèi),而大型公司也很少開源他們的源代碼。因此,與其他平臺(tái)相比,Unity想要整理出一套通用前端技術(shù)框架確實(shí)面臨著很多挑戰(zhàn)。
1.2業(yè)界常用開源Unity框架
下面分析一下市面上常見的Unity架構(gòu),并列舉不適合我們的原因。
?UnityGameFramework
UnityGameFramework使用一套UnityFramework和一套Gameframework對(duì)Unity進(jìn)行了一次封裝。
在封裝的基礎(chǔ)上做了一些方便開發(fā)者使用的擴(kuò)展,如ECS/UI等功能。
?QFramework
QFramework 是提供一套簡單、強(qiáng)大、易上手、符合 SOLID 原則、支持領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)、事件驅(qū)動(dòng)、數(shù)據(jù)驅(qū)動(dòng)、分層、MVC 、CQRS、模塊化、易擴(kuò)展的架構(gòu)。
1.3場(chǎng)景適用性思考
以上兩個(gè)架構(gòu)已足夠優(yōu)秀,但是要集成到我們的技術(shù)棧中還是有很多挑戰(zhàn):
?UnityGameFramework
這套架構(gòu)太“重”了,使用A模塊必須依賴架構(gòu)內(nèi)的B模塊甚至C/D/E模塊,只想使用簡單的UI功能可能要把整套架構(gòu)都遷移進(jìn)來。
太“重”也引起了修改一個(gè)模塊會(huì)牽連很多其他模塊的問題。
適合需求明確的中重度游戲,商業(yè)化項(xiàng)目。
?QFramework
學(xué)習(xí)成本較高,需要理解很多設(shè)計(jì)原則才可以上手使用。
它與UnityGameFramework相比又太“輕”了,源碼少,可魔改的余地少。適合小而精的項(xiàng)目。
?其他
其他架構(gòu)都缺少線上足夠項(xiàng)目實(shí)際驗(yàn)證與配套的開源生態(tài),健壯性與擴(kuò)展性無法確保。
1.4架構(gòu)關(guān)注點(diǎn)思考
好的架構(gòu)應(yīng)該注重以下幾個(gè)方面:
?生命周期
良好的生命周期設(shè)計(jì),可以提供簡單而高效的生命周期管理機(jī)制使開發(fā)人員在合適的時(shí)機(jī)創(chuàng)建、修改和銷毀對(duì)象。
生命周期感興趣的同學(xué)可以深入了解一下Unity的MonoBehavior設(shè)計(jì)。
?分層設(shè)計(jì)
分層設(shè)計(jì)可以使代碼解耦,將參考后端多種架構(gòu)設(shè)計(jì)理念,MVC、DDD、洋蔥架構(gòu)等,免代碼耦合,為提高架構(gòu)防腐度,降低續(xù)的化和重構(gòu)提的頻率。
?學(xué)習(xí)成本
考慮到員工技能水平的參差不齊,學(xué)習(xí)成本是設(shè)計(jì)架構(gòu)時(shí)最需要考慮的因素之一。,果架構(gòu)過于“重”,那么就需要了解很多底層/中間層邏輯才能使用,且出現(xiàn)問題后也不易于修改。
?上線驗(yàn)證
如果一套架構(gòu)已經(jīng)通過多個(gè)項(xiàng)目的上線驗(yàn)證,那么就不太需要擔(dān)心架構(gòu)中還有未解決的問題。開源架構(gòu)都會(huì)列出自己的產(chǎn)品案例。
2.之家Unity架構(gòu)設(shè)計(jì)
綜合上述總結(jié),在設(shè)計(jì)Unity通用架構(gòu)時(shí)重點(diǎn)考慮了分層設(shè)計(jì),好的分層邊界能降低學(xué)習(xí)成本提高復(fù)用性。
2.1分層設(shè)計(jì)
汽車之家Unity通用架構(gòu)采用四層設(shè)計(jì):邏輯層、中間層、基礎(chǔ)層和數(shù)據(jù)層。
?邏輯層
邏輯層處理不同項(xiàng)目的交互邏輯,調(diào)用中間層和基礎(chǔ)層功能。在邏輯層中,可以按照項(xiàng)目需求進(jìn)行設(shè)計(jì),而不需要考慮復(fù)用性。
具體模型和數(shù)據(jù)功能通過調(diào)用底基礎(chǔ)層和數(shù)據(jù)層接口現(xiàn)。
?中間層
中間層對(duì)邏輯層和基礎(chǔ)層進(jìn)行封裝,使得邏輯層調(diào)用更加清晰,基礎(chǔ)層有更好的抽象環(huán)境。
中間層又分為業(yè)務(wù)層和適配器層。業(yè)務(wù)層主要針對(duì)邏輯層進(jìn)行封裝和特殊處理,而適配器層則對(duì)基礎(chǔ)層進(jìn)行二次封裝,組合多個(gè)基礎(chǔ)層能力以應(yīng)對(duì)復(fù)雜功能。
?基礎(chǔ)層
基礎(chǔ)層對(duì)基礎(chǔ)功能進(jìn)行抽象,使用統(tǒng)一的接口設(shè)計(jì),支持所有Unity項(xiàng)目。這一層可以使用市面上普及的解決方案如TMP/DoTween等。
基礎(chǔ)層應(yīng)對(duì)功能抽象,不關(guān)心具體需求,具有良好的健壯性和可擴(kuò)展性。
?數(shù)據(jù)層
數(shù)據(jù)層用于后臺(tái)存儲(chǔ)、數(shù)據(jù)和模型信息等。只要使用同樣的后臺(tái)服務(wù)和美術(shù)規(guī)范,新的Unity項(xiàng)目就不需要對(duì)數(shù)據(jù)層再做兼容。
如有特殊需求,也可以在中間層對(duì)數(shù)據(jù)層進(jìn)行處理,參考洋蔥架構(gòu)設(shè)計(jì)。
2.2架構(gòu)圖
以下是汽車之家Unity通用架構(gòu)的架構(gòu)設(shè)計(jì)圖與銷冠神器使用通用架構(gòu)后的架構(gòu)圖:
?Unity通用架構(gòu)圖
?銷冠神器架構(gòu)圖
2.3代碼示例
以原生端通信功能為例,說明分層和復(fù)用性設(shè)計(jì)在架構(gòu)中的體現(xiàn)。
這里ativeMessage是一個(gè)可以與原生端進(jìn)行通信的模塊。該模塊負(fù)責(zé)向iOS和Android平臺(tái)發(fā)送和接收消息,用于處理一些原生交互的邏輯。
基礎(chǔ)層的NativeMessage在Plugin文件夾中,只有核心的發(fā)送消息和接受消息的能力
中間層的XGNativeMessage在Scripts/Manager文件夾中,繼承基礎(chǔ)層并添加業(yè)務(wù)相關(guān)的設(shè)置。
邏輯層在Module或Controller中對(duì)中間層的XGNativeMessage進(jìn)行調(diào)用
大致流程如下:
?優(yōu)勢(shì)總結(jié):
這種設(shè)計(jì)可以確?;A(chǔ)層有100%的復(fù)用性,使其可以方便地將其遷移至其他項(xiàng)目中使用。此外,中間層的封裝可以集中處理發(fā)送消息的邏輯,從而避免在邏輯層中編寫大量代碼。
采用分層設(shè)計(jì)的具有很方便的升級(jí)和擴(kuò)展性。如果需要對(duì)其中某一層進(jìn)行升級(jí),可以直接修改對(duì)應(yīng)層級(jí)的代碼,而不會(huì)影響其他層的功能。這使得系統(tǒng)更加靈活和可維護(hù)。
分層設(shè)計(jì)和復(fù)用性是非常重要的架構(gòu)設(shè)計(jì)原則。在NativeMessage模塊的設(shè)計(jì)中,成功應(yīng)用了這些原則,使得該模塊具有高度的可復(fù)用性和可維護(hù)性。
3.架構(gòu)收益
通用架構(gòu)1.0上線后,我們量化了架構(gòu)收益:
?代碼質(zhì)量 升20%
底層和中間層按照功能解耦,可以提高代碼質(zhì)量,也降低單個(gè)迭代SP的bug率20%以上。
?開發(fā)效率 升30%
按照相同的框架發(fā)可規(guī)范,高開單人力研發(fā)需求交付效率30%以上同時(shí),不同項(xiàng)目組之間可以共享同一套底層功能,從而互相幫助和提高生產(chǎn)力。
代碼規(guī)范和模塊拆分的方式符合Unity行業(yè)的通用解決方案,這可以幫助Unity開發(fā)人員更快地理解和掌握項(xiàng)目的架構(gòu)設(shè)計(jì)和開發(fā)規(guī)范。
?各項(xiàng)性能指標(biāo)提升20%
通過架構(gòu)升級(jí),不僅解耦了代碼,還帶來了其他收益。例如,將GLB升級(jí)為AssetBundle,可以顯著降低內(nèi)存占用量,并減少CPU負(fù)載30%以上。
功能模塊化設(shè)計(jì)使得我們可以更好地統(tǒng)計(jì)啟動(dòng)時(shí)各個(gè)階段所占用的時(shí)間,并針對(duì)下載/加載等階段進(jìn)行優(yōu)化,從而使啟動(dòng)時(shí)間降低了50%。
這些優(yōu)化措施可以進(jìn)一步提高應(yīng)用程序的性能和用戶體驗(yàn),提高產(chǎn)品的競(jìng)爭力。
?跨項(xiàng)目代碼復(fù)用度提升50%
通用架構(gòu)需要支持之家的所有Unity項(xiàng)目,所以需要考慮不同項(xiàng)目中的代碼復(fù)用。代碼復(fù)用性可以根據(jù)分層由低到高來考慮,最底層的代碼復(fù)用性越高。
邏輯層復(fù)用率0%,因?yàn)槊總€(gè)項(xiàng)目的交互邏輯不同,過多考慮復(fù)用會(huì)引起很多問題。這一層不需要考慮復(fù)用性的設(shè)計(jì)。
中間層復(fù)用率60%,中間層對(duì)邏輯層和基礎(chǔ)層進(jìn)行抽象和二次封裝,應(yīng)該在開發(fā)過程中盡量考慮復(fù)用性。至少適配器層要能快速地復(fù)用到其他項(xiàng)目中。
基礎(chǔ)層復(fù)用率100%,基礎(chǔ)層抽象基礎(chǔ)功能,只考慮功能而不關(guān)心業(yè)務(wù)。
數(shù)據(jù)層復(fù)用率100%,數(shù)據(jù)層由后端提供,使用相同的服務(wù)和美術(shù)規(guī)范。
4.總結(jié)
分層設(shè)計(jì)降低了上手成本,只要邏輯層足夠清晰簡單,那么初級(jí)程序員就可以很容易的去寫一些業(yè)務(wù)相關(guān)的功能,有能力的程序員可以持續(xù)為架構(gòu)輸出健壯的中間層和底層能力。邏輯層只采用最簡單的狀態(tài)機(jī)設(shè)計(jì),如果之后業(yè)務(wù)需求復(fù)雜也可以擴(kuò)展成分層狀態(tài)機(jī)來實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)需求。
5.經(jīng)驗(yàn)分享
架構(gòu)設(shè)計(jì)應(yīng)該注重分層設(shè)計(jì)與上手成本,當(dāng)這兩點(diǎn)設(shè)計(jì)較好時(shí),像易用性,復(fù)用性,解耦等優(yōu)點(diǎn)就會(huì)自然出現(xiàn)。
分層設(shè)計(jì)可以讓業(yè)務(wù)代碼不會(huì)侵入功能代碼,而學(xué)上手本低也會(huì)帶來易維護(hù),提效等好處。
6.引用
分享一下本文所引用的架構(gòu)鏈接:
UnityGameFramework:
https://github.com/EllanJiang/UnityGameFramework
QFramework:
https://github.com/liangxiegame/QFramework
本文使用ChatGPT幫忙檢查語法和拼寫錯(cuò)誤,并提供優(yōu)化建議以提高文章的流暢性和可讀性。
作者簡介
胡春源
■ 主機(jī)廠事業(yè)部-創(chuàng)新項(xiàng)目團(tuán)隊(duì)
■ 2022年2月入職汽車之家,先后負(fù)責(zé)VI銷冠神器和全息倉的架構(gòu),優(yōu)化,功能開發(fā)等工作?,F(xiàn)在主要負(fù)責(zé)Unity項(xiàng)目的架構(gòu)和功能的相關(guān)工作。