Unity3D 官方教程:WebGL(二)
部署壓縮工程
當你在釋出模式下構建WebGL專案時,Unity會將你工程的輸出檔案進行壓縮,以降低工程下載的份量。你可以在釋出設定中的壓縮格式選項裡,選擇壓縮的型別(選單:Edit->Project Settings -> Player -> Publishing Settings):
- gzip:這是預設選項。gzip檔案比Brotli檔案更大,但構建速度更快,並且被所有瀏覽器在http協議和https協議都原生支援。檔名會有.gzip的額外字尾。
- Brotli:Brotli壓縮提供了最棒的壓縮率。Brotli壓縮檔案明顯比gzip檔案小,但會花很長時間來壓縮,增加了你釋出版工程的迭代時間。Brotli押送被Chrome和Firefox在https協議中原生支援(檢視WebGL瀏覽器相容性來獲得更多資訊)。Brotli壓縮檔案會有.br字尾。
- Disabled:這禁用了壓縮功能。如果你希望在預處理指令碼中實現你自己的壓縮,使用這個選項。
壓縮構建的Unity工程可以在任何瀏覽器上工作。Unity 包含了一個用JavaScript編寫的軟體解壓器,當伺服器端不啟用http壓縮傳輸時,它會回退。資料被瀏覽器從伺服器上下載,並且被Unity的載入器程式碼所解壓縮。當這些完成時,在你瀏覽器的JavaScript控制檯中出現資訊(包含了你的檔名而不是這裡的例子):
82毫秒完成解壓縮<Example/MyProject.jsgz>。如果你設定網頁瀏覽器使用壓縮來管理檔案,你可以移除這個延遲。
這裡,82毫秒只是個例子;花費的毫秒數量依賴於內容大小,以及計算機的速度。更大的工程花費更長的解壓縮時間,更快的計算機消耗更少的時間。將解壓縮時間打出,以提示你:你可以通過讓瀏覽器掌控解壓縮,來節約多少啟動時間。
進階:瀏覽器本地解壓
瀏覽器可以在它下載Unity工程的資料時就在本地進行解壓。這有避免了因在JavaScript中解壓縮檔案而產生額外延遲的好處,減少了啟動時間。為了讓瀏覽器進行本地解壓,需要配置網頁伺服器用正確的http頭提供壓縮檔案:這告訴瀏覽器,資料使用gzip或者Brotli方式壓縮,從而瀏覽器在資料開始傳輸時就解壓。Brotli壓縮被Firefox和Chrome僅在https協議中支援,而gzip壓縮被所有瀏覽器支援。檢視WebGL browser compatibility 來獲取更多資訊。
設定網頁伺服器
對瀏覽器本地解壓的設定過程依賴於你的網頁伺服器。本頁的說明適用於兩種最主流的網頁伺服器,Apache和IIS。注意,這些在預設設定下可用,但可能需要調整以匹配你的個性化設定。尤其,如果你已經有了另一個伺服器端配置來壓縮本地檔案時,可能會有妨礙這裡設定的問題。
Apache
Apache使用不可見的.htaccess檔案進行伺服器設定。下方的樣例程式碼展示了一個.htaccess檔案的例子,你可以放進你的發行目錄來配置Apache,以掌控你的壓縮檔案。
<IfModule mod_rewrite.c>
<IfModule mod_mime.c>
Options +SymLinksIfOwnerMatch
RewriteEngine on
RewriteCond %{HTTP:Accept-encoding} br
RewriteCond %{REQUEST_FILENAME}br -f
RewriteRule ^(.*)\.(js|data|mem|unity3d)$ $1.$2br [L]
AddEncoding br .jsbr
AddEncoding br .databr
AddEncoding br .membr
AddEncoding br .unity3dbr
RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME}gz -f
RewriteRule ^(.*)\.(js|data|mem|unity3d)$ $1.$2gz [L]
AddEncoding gzip .jsgz
AddEncoding gzip .datagz
AddEncoding gzip .memgz
AddEncoding gzip .unity3dgz
</IfModule>
</IfModule>
當Apache接收到一個對檔案的請求(例如Release/mgame.js),這裡的配置檢查,客戶端是否允許Brotli-編碼的資料(RewriteCond %{HTTP:Accept-encoding} br),然後檢查在 Release/mygame.jsb**r 是否有檔案 (RewriteCond %{REQUEST_FILENAME}br -f)。如果兩種情況都匹配,Apach重寫請求到.jsbr檔案中,並響應。AddEncoding br .jsbr 通知Apache通過新增頭部來告訴客戶端,檔案使用Brotli編碼。
隨後的樣例程式碼塊對gzip做相同設定。因此,如果 Release/mygame.jsgz 檔案存在、但Brotli壓縮的條件不成立,Apache會用.gzip格式檔案處理。
IIS
IIS使用web.config檔案進行伺服器配置。以下樣例程式碼展示了一個web.config檔案的例子,你可以放到你的Release目錄中來配置IIS如何處理壓縮檔案。
為了使用這個,你需要安裝Microsoft的IIS URL Rewrite IIS 模組;否則,瀏覽器會丟擲一個500 內部伺服器錯誤。如果你沒有安裝這個模組,你扔可以使用這個檔案,但沒有在< rewrite>和< /rewrite>之間的程式碼。這無法讓壓縮傳輸可用,但讓IIS可以處理檔案擴充套件。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<staticContent>
<remove fileExtension=".mem" />
<remove fileExtension=".data" />
<remove fileExtension=".unity3d" />
<remove fileExtension=".jsbr" />
<remove fileExtension=".membr" />
<remove fileExtension=".databr" />
<remove fileExtension=".unity3dbr" />
<remove fileExtension=".jsgz" />
<remove fileExtension=".memgz" />
<remove fileExtension=".datagz" />
<remove fileExtension=".unity3dgz" />
<mimeMap fileExtension=".mem" mimeType="application/octet-stream" />
<mimeMap fileExtension=".data" mimeType="application/octet-stream" />
<mimeMap fileExtension=".unity3d" mimeType="application/octet-stream" />
<mimeMap fileExtension=".jsbr" mimeType="application/octet-stream" />
<mimeMap fileExtension=".membr" mimeType="application/octet-stream" />
<mimeMap fileExtension=".databr" mimeType="application/octet-stream" />
<mimeMap fileExtension=".unity3dbr" mimeType="application/octet-stream" />
<mimeMap fileExtension=".jsgz" mimeType="application/octet-stream" />
<mimeMap fileExtension=".memgz" mimeType="application/octet-stream" />
<mimeMap fileExtension=".datagz" mimeType="application/octet-stream" />
<mimeMap fileExtension=".unity3dgz" mimeType="application/octet-stream" />
</staticContent>
<rewrite>
<rules>
<rule name="Append br suffix to WebGL content requests">
<match url="(.*)\.(js|data|mem|unity3d)$" />
<conditions>
<add input="{HTTP_ACCEPT_ENCODING}" pattern="br" />
<add input="{REQUEST_FILENAME}br" matchType="IsFile" />
</conditions>
<action type="Rewrite" url="{R:1}.{R:2}br" />
</rule>
<rule name="Append gz suffix to WebGL content requests">
<match url="(.*)\.(js|data|mem|unity3d)$" />
<conditions>
<add input="{HTTP_ACCEPT_ENCODING}" pattern="gzip" />
<add input="{REQUEST_FILENAME}gz" matchType="IsFile" />
</conditions>
<action type="Rewrite" url="{R:1}.{R:2}gz" />
</rule>
</rules>
<outboundRules>
<rule name="Append br Content-Encoding header to the rewritten responses">
<match serverVariable="RESPONSE_Content-Encoding" pattern=".*" />
<conditions>
<add input="{REQUEST_FILENAME}" pattern="\.(js|data|mem|unity3d)br$" />
</conditions>
<action type="Rewrite" value="br" />
</rule>
<rule name="Append gzip Content-Encoding header to the rewritten responses">
<match serverVariable="RESPONSE_Content-Encoding" pattern=".*" />
<conditions>
<add input="{REQUEST_FILENAME}" pattern="\.(js|data|mem|unity3d)gz$" />
</conditions>
<action type="Rewrite" value="gzip" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
如果這些擴充套件可以在更高一級的目錄結構中被覆蓋,你只需要 《remove fileExtension=”.*” 》這一行。
WebGL工程的除錯及問題捕獲
Unity WebGL內容無法正確地被除錯用MonoDevelop或者Visual Studio,這讓你很難找出到底是什麼東西出錯了。這裡有些提示關於如何從你的工程中獲得資訊。
瀏覽器的JavaScript控制檯
Unity WebGL 沒有對你檔案系統的存取,所以無法像其它平臺那樣寫入一個日誌檔案。然而,它會將所有可能寫入日誌的資訊(例如Debug.Log,Console.WriteLine 或者Unity的內部日誌)寫到瀏覽器的JavaScript控制檯中。
- 對於Firefox,你可以通過在Windows系統中按下Ctrl-Shift-K 、或者在Mac中按下 Command-Option-K 開啟JavaScript控制檯。
- 對於Chrome,你可以通過在Windows系統中按下 Ctrl-Shift-J 、或者在Mac中按下Command-Option-J 開啟JavaScript控制檯。
- 對於Safari,你可以通過在Preferences中的Advanced表內啟用開發選單,然後按下 Command-Option-C來開啟JavaScript控制檯。
- 對於Microsoft Edge 或者Internet Explorer,你可以通過按下F12來開啟JavaScript控制檯。
開發模式工程
出於除錯目的,你可能希望在Unity中建立一個開發模式的工程(開發模式工程選項框在構建設定視窗中)。開發模式工程允許你連線分析工具,並且他們不會被壓縮,這樣產生的JavaScript程式碼會仍然包含可讀的函式名(儘管C++處理了)。當你執行到一個瀏覽器錯誤,或者當你丟擲一個異常、並且異常支援被禁用,或者在使用Debug.LogError時,這可以通過瀏覽器顯示棧追蹤來使用分析工具。不像在啟用完整異常支援(見下方)時你可以得到可控的棧追蹤,這些棧追蹤會有奇怪的名字,並且不僅包含託管程式碼,也包括了內部的Unity引擎程式碼。
異常支援Exception support
WebGL有不同級別的異常支援(檢視Building for WebGL頁面)。預設情況下,Unity WebGL會僅支援明顯丟擲的異常。你可以啟用完全異常支援,這會額外選擇在IL2CPP生成程式碼,在你的程式碼中捕獲對空引用及越界陣列元素的存取。這些額外的選項會明顯影響到執行效能,增加程式碼大小及載入時間,所以這個模式僅推薦在除錯中使用。
完整異常支援也將函式名發射來對於你的程式碼生成棧追蹤。這樣,對於未捕獲的異常及Debug.Log狀態,你會在控制檯中看到棧追蹤,並且你可以使用 System.Environment.Stacktrace 來得到棧追蹤字串。