最近看到很多人討論這個,也有一些分析的文章,但是我認為最靠譜的還是來自知乎的一篇分析, 作者把黑神話逆向,解包之後,得出的結論是:
黑神話的指令碼方案是魔改的USharp,自己實現了mono/clr/il2cpp的執行模式,且支援全平臺(PC/Mac/Linux/Android/iOS/PS5/XBox)。
以下是原文內容:
地址:https://zhuanlan.zhihu.com/p/715690420
作者:John
前言
《黑神話:悟空》上線了,第一時間下載體驗了一下。然後很好奇他們用的是什麼指令碼方案,因為大型UE專案絕不可能純C++開發,所以解包看了一下,也發現一點有意思的東西。
黑神話檔案目錄
其實上線之前,他們官方就發了一個免費的測試工具,實際上這個測試工具是包含完整的程式碼的,只是剔除了大部分遊戲資源。因為專案組不可能有精力從頭搞一個新工程來做測試工具,剔除資源比剔除程式碼容易一萬倍,程式設計師應該都懂。
引擎版本
首先是引擎版本,大家都知道他們一開始是UE4,UE5首發之後他們就切換到UE5了,所以引擎版本是UE5.0.0。之後雖然Epic釋出了更新的UE5.0.3等版本,但是專案組一般不會輕易升級的。可能只是移植一些需要的程式碼過來,畢竟換引擎的話,以前的大量魔改不好遷移。
遊戲入口exe
程式碼段大小
有一點值得注意的是,exe的大小達到了859MB,這個程式碼段大小不太正常。參考同樣是UE開發的遊戲,三角洲行動端遊140MB,極品飛車集結端遊105MB。感覺可能是包含了太多沒用的外掛程式碼或者沒剔除一些不必要的符號?
指令碼方案
在檢視程式碼符號時,我發現了大量V8的欄位,所以理所當然的以為竟然用了PuerTS,覺得專案組還挺跟隨潮流。但是卻搜不到PuerTS相關的符號,轉而搜尋js,發現程式碼中包含了Unreal.js外掛。
Unreal.js是一個N年前的外掛,一直沒維護,去年才加了UE5的支援。看起來黑神話對這個外掛做了些修改。
就這樣,我以為用的是Unreal.js,直到開始解包pak才發現並沒有這麼簡單。
Pak解包
解包UE的Pak,一般要知道對應版本的引擎和AESKey,因為每個版本PakInfo結構不太一樣。這裏不太適合公開細節,略過。
直接說結果,我發現Pak中找不到類似js、ts、wasm的程式碼檔案,所以可能他們繼承了這個外掛但是沒有用。也可能是用其他方式儲存了。
但是翻Pak檔案我發現大量存在的兩種二進制檔案,.data和.Data。小寫開頭的像是配置檔案,大寫開頭的像是某種程式碼的二進制檔案。
如下 .data 檔案,就是物品的配置,看起來包含了物品的藍圖路徑和其他配置內容,是類似protobuf的結構(因為儲存的目錄名是PBTable,在遊戲行業使用PB儲存配置是很常用的方式):
.data
如下.Data 檔案看起來 就像是某種程式碼的二進制,但按我的經驗js或者ts應該不是這樣,倒像是一種自定義的狀態機的樣子(根據後續分析,確實是一種用於策劃編輯的自定義藍圖結構):
.Data
這就奇怪了,沒有js程式碼,也沒有找到類似luac的程式碼,但是既然有類似二進制的程式碼,那麼是不是用了C#相關方案呢?比如USharp、UnrealCLR、UnrealSharp,直接在程式碼符號中搜索相關字串果然找到了USharp,並且Pak中也有USharp.uplugin檔案,所以可以確定用了USharp。
SharpClass
上圖可以看到藍圖節點中大量使用了SharpClass,也就是USharp的自定義UBlueprintGeneratedClass,用於執行時將C#中的自定義UClass動態生成UE的型別。
USharp.uplugin
但是,貌似沒這麼簡單,因為USharp不支援UE5,並且不支援主機和移動端,但是黑神話包內的uplugin檔案包含了這些平臺。我想黑神話官方對USharp進行了大量的魔改和相容。
但到這裏我還是沒搞清楚黑神話到底用了什麼指令碼方案,因為Pak中並沒有找到js、lua或者USharp的dll檔案。可是明明程式碼中用了Unreal.js和USharp外掛。
彆着急,繼續往下看。
il2cpp
提到il2cpp,Unity開發者們都很熟悉,爲了解決mono的相容性和效能等問題推出的方案。
但是這是Unity專屬的,跟黑神話有什麼關係?在檢視USharp相關符號時,我發現一個令人震驚的事實,黑神話所使用的USharp和原版並不一樣,提供了USharp執行模式的切換,其中包含了主流的mono、clr,以及il2cpp!
il2cpp
這些模式與設定都是原版USharp並不包含的內容,也就是說,專案組爲了相容性和效能做了大量最佳化和魔改,完全可以說基於USharp重新開發了一個C#的指令碼方案,支援mono、clr和il2cpp。
那麼既然Pak中沒包含dll或者指令碼,顯然在Release版本中他們使用了il2cpp,所以,C#中定義的型別和各種符號都跑到了C++中,也就是最終的exe裡面。這也是導致exe如此大的根本原因。
根據評論區的補充,黑神話的程式碼符號中除了il2cpp,還包含了Mono和UnityEngine的部分等dll,可以確定同時使用了Mono和Unity il2cpp的程式碼,但具體使用了哪種方式還沒法確定。
C#符號
實際上如果打包成dll,可能只有幾十MB,exe可以降到100MB,不過效能會略有損失。
總結
總結一下,黑神話的指令碼方案是魔改的USharp,自己實現了mono/clr/il2cpp的執行模式,且支援全平臺(PC/Mac/Linux/Android/iOS/PS5/XBox)。
此外,程式碼整合了Unreal.js但是貌似沒用到,還使用了自研的某種狀態機/行為樹,配置表使用的是protobuf結構的二進制資料。