Menjalankan WebGL Perpaduan dengan Teras ASP.NET
Persekitaran pengesahan
- Windows
-
- Windows 11
- Penyunting Perpaduan
-
- 2020.3.25f1
- Visual Studio
-
- Visual Studio 2022
- ASP.NET Teras
-
- ASP.NET Teras 6.0
- Perkhidmatan Maklumat Internet (IIS)
-
- IIS 10.0
Pada mulanya
Ketahui cara menjalankan output permainan sebagai WebGL dalam Unity pada pelayan web yang menjalankan ASP.NET Core. Untuk program permainan, gunakan output dalam langkah petua di bawah. Contoh permainan menggunakan 2D Platformer Microgame, yang boleh dibuat dari Hab Perpaduan.
Saya akan menerangkan bagaimana untuk menubuhkan "Uncompressed WebGL", "WebGL dimampatkan dengan Gzip", dan "WebGL dimampatkan dengan Brotli" untuk menjalankan permainan WebGL. Prosedur ini adalah sama untuk mereka semua.
Kami menggunakan Visual Studio 2022, ASP.NET Core 6.0, tetapi versi lama mungkin akan berfungsi. Walau bagaimanapun, struktur kod awal berbeza untuk setiap versi, jadi sila fahami perbezaannya sendiri.
Mewujudkan Projek Teras ASP.NET
Lancarkan "Visual Studio 2022" dari menu mula.
Pilih Cipta Projek Baru.
Kali ini, pilih "ASP.NET Core Web App" sebagai sampel. Jika anda menjalankan ASP.NET Core, anda boleh menjalankan templat lain tetapi anda perlu mengikuti setiap templat tentang cara membinanya.
Tetapkan nama dan lokasi projek sewenang-wenangnya.
Tinggalkan maklumat tambahan seperti itu.
Projek ini telah diwujudkan.
Menjalankan WebGL yang tidak dimampatkan
Sediakan program WebGL yang dibuat tanpa pemampatan.
Pastikan permainan berfungsi dengan cepat
ASP.NET Cuba jalankan permainan WebGL dengan tetapan yang lebih sedikit tanpa mengikut etika Core.
Dalam ASP.NET Core, anda tidak boleh mengakses beberapa fail WebGL yang dipancarkan oleh Unity dalam keadaan lalai. Jadikan ini boleh diakses.
Program.cs
Buka daripada projek anda Program.cs
. Digunakan pada versi Startup.cs
Teras ASP.NET terdahulu .
Tambah ruang nama di bahagian atas kod dan gantikan yang berikut dalam kod:app.UseStaticFiles();
// ここから追加
using Microsoft.AspNetCore.StaticFiles;
// ここまで追加
var builder = WebApplication.CreateBuilder(args);
// --- 省略 ---
app.UseHttpsRedirection();
//app.UseStaticFiles();
// ここから追加
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".data"] = "application/octet-stream";
provider.Mappings[".wasm"] = "application/wasm";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = provider,
});
// ここまで追加
app.UseRouting();
// --- 省略 ---
.data
, supaya apabila fail diakses, .wasm
ia boleh dikembalikan kepada pelanggan dengan yang ditentukan Content-Type
.
Penggunaan WebGL
Letakkan folder fail berikut daripada Unity dalam projek wwwroot
anda .
- indeks.html
- Membina
- TemplatData
Index.cshtml
index.html
Buka pautan supaya anda boleh mengaksesnya.
<!-- 省略 -->
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
<!-- 追加 -->
<a href="index.html">index.html</a>
Jalankan program dan pastikan permainan berfungsi.
Menjalankan program WebGL pada halaman Pisau Cukur
Permainan sebelumnya berjalan pada fail HTML statik, jadi ia berjalan di tempat yang tidak ada kaitan dengan ASP.NET Core. Ia tidak begitu diingini untuk keseragaman program, jadi kami akan memindahkan tingkah laku fail HTML ke Halaman Cukur.
Klik kanan folder Pages daripada projek anda untuk menambah item baru.
Pilih halaman pisau cukur - kosong. Tiada nama tertentu yang dinyatakan, tetapi ia ditambah di sini WebGL.cshtml
.
Kod dipaparkan.
index.html
Rujuk kandungan fail dan port ke WebGL.cshtml
.
link
Terdapat beberapa perkara pelik, seperti cara meletakkan tag, tetapi saya akan meninggalkannya kerana ia adalah demi kesederhanaan penjelasan.
@page
@model UnityPublishWebglAspNetCore.Pages.WebGLModel
@{
}
<div id="unity-container" class="unity-desktop">
<canvas id="unity-canvas" width=960 height=600></canvas>
<div id="unity-loading-bar">
<div id="unity-logo"></div>
<div id="unity-progress-bar-empty">
<div id="unity-progress-bar-full"></div>
</div>
</div>
<div id="unity-warning"> </div>
<div id="unity-footer">
<div id="unity-webgl-logo"></div>
<div id="unity-fullscreen-button"></div>
<div id="unity-build-title">Platformer</div>
</div>
</div>
@section Scripts {
<link rel="shortcut icon" href="TemplateData/favicon.ico">
<link rel="stylesheet" href="TemplateData/style.css">
<script>
var container = document.querySelector("#unity-container");
var canvas = document.querySelector("#unity-canvas");
var loadingBar = document.querySelector("#unity-loading-bar");
var progressBarFull = document.querySelector("#unity-progress-bar-full");
var fullscreenButton = document.querySelector("#unity-fullscreen-button");
var warningBanner = document.querySelector("#unity-warning");
// 一時的なメッセージバナー/リボンを数秒間表示するか、
// type == 'error'の場合はキャンバスの上部に永続的なエラーメッセージを表示します。
// type == 'warning'の場合、黄色のハイライト色が使用されます。
// この関数を変更または削除して、重要ではない警告とエラーメッセージがユーザーに表示されるように
// 視覚的に表示される方法をカスタマイズします。
function unityShowBanner(msg, type) {
function updateBannerVisibility() {
warningBanner.style.display = warningBanner.children.length ? 'block' : 'none';
}
var div = document.createElement('div');
div.innerHTML = msg;
warningBanner.appendChild(div);
if (type == 'error') div.style = 'background: red; padding: 10px;';
else {
if (type == 'warning') div.style = 'background: yellow; padding: 10px;';
setTimeout(function() {
warningBanner.removeChild(div);
updateBannerVisibility();
}, 5000);
}
updateBannerVisibility();
}
var buildUrl = "Build";
var loaderUrl = buildUrl + "/WebGL.loader.js";
var config = {
dataUrl: buildUrl + "/WebGL.data",
frameworkUrl: buildUrl + "/WebGL.framework.js",
codeUrl: buildUrl + "/WebGL.wasm",
streamingAssetsUrl: "StreamingAssets",
companyName: "DefaultCompany",
productName: "Platformer",
productVersion: "2.1.0",
showBanner: unityShowBanner,
};
// デフォルトでは、Unity は WebGL キャンバスレンダリングのターゲットサイズを
// キャンバス要素の DOM サイズ(window.devicePixelRatio でスケーリング)と一致させます。
// この同期がエンジン内で発生しないようにする場合は、これを false に設定し、
// 代わりにサイズを大きくします。 キャンバスの DOM サイズと WebGL は、
// ターゲットサイズを自分でレンダリングします。
// config.matchWebGLToCanvasSize = false;
if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
container.className = "unity-mobile";
// モバイルデバイスでフィルレートのパフォーマンスを低下させないようにし、
// モバイルブラウザで低 DPI モードをデフォルト/オーバーライドします。
config.devicePixelRatio = 1;
unityShowBanner('WebGL builds are not supported on mobile devices.');
} else {
canvas.style.width = "960px";
canvas.style.height = "600px";
}
loadingBar.style.display = "block";
var script = document.createElement("script");
script.src = loaderUrl;
script.onload = () => {
createUnityInstance(canvas, config, (progress) => {
progressBarFull.style.width = 100 * progress + "%";
}).then((unityInstance) => {
loadingBar.style.display = "none";
fullscreenButton.onclick = () => {
unityInstance.SetFullscreen(1);
};
}).catch((message) => {
alert(message);
});
};
document.body.appendChild(script);
</script>
}
Index.cshtml
WebGL
Tambah pautan ke .
<!-- 省略 -->
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
<!-- 追加 -->
<ul>
<li><a href="index.html">index.html</a></li>
<li><a href="WebGL">WebGL</a></li>
</ul>
Cuba jalankan program ini. Anda boleh melihat bahawa pengepala dan pengaki _Layout.cshtml
dipaparkan pada halaman WebGL mengikut .
Tukar lokasi fail WebGL
Saya meletakkan fail WebGL secara langsung di bawah , tetapi kaedah ini akan menulis ganti apabila anda meletakkan dua atau lebih fail WebGL wwwroot
.
Saya akan menerangkan cara memasukkannya ke dalam folder berasingan dan mengalihkannya.
Pertama sekali, buat folder baru yang dipanggil "webgl" dan alihkannya ke sana. Dua folder Build
yang akan dialihkan ialah , TemplateData
.
index.html
Saya telah mengalihkannya ke Halaman Pisau Cukur dan boleh memadamkannya dengan selamat.
Oleh kerana WebGL.cshtml
kami telah memperdalam hierarki folder, kami juga akan memperdalam laluan yang diterangkan dalam . Pembetulan ialah 3 baris.
Sebelum pembetulan
<link rel="shortcut icon" href="TemplateData/favicon.ico">
<link rel="stylesheet" href="TemplateData/style.css">
var buildUrl = "Build";
Selepas pembetulan
<link rel="shortcut icon" href="webgl/TemplateData/favicon.ico">
<link rel="stylesheet" href="webgl/TemplateData/style.css">
var buildUrl = "webgl/Build";
Jalankan program untuk melihat sama ada ia berfungsi dengan baik.
Menjalankan WebGL dimampatkan dengan Gzip
Pelanjutan fail yang dimampatkan oleh Gzip ialah .gz
, dan ia adalah fail yang boleh dikendalikan oleh ASP.NET Core,
Unity WebGL Content-Type
dan dikendalikan secara berbeza dan memerlukan penukaran.
Mula-mula, cipta penggunaan fail dan halaman WebGL.
Peletakan fail WebGL
wwwroot
webgl-gzip
Buat folder di bawah Gzip dan salin folder dari fail Build
TemplateData
WebGL yang anda buat dengan Gzip.
Buat Laman Pisau Cukur
Kali WebGLGzip.cshtml
ini mencipta fail menggunakan prosedur yang sama seperti apabila tidak dimampatkan.
Kod ini adalah seperti berikut dengan merujuk kepada Output dalam index.html
Perpaduan.
Laluan ini sepadan dengan folder yang anda buat webgl-gzip
sebelum ini untuk fail WebGL.
@page
@model UnityPublishWebglAspNetCore.Pages.WebGLGzipModel
@{
}
<div id="unity-container" class="unity-desktop">
<canvas id="unity-canvas" width=960 height=600></canvas>
<div id="unity-loading-bar">
<div id="unity-logo"></div>
<div id="unity-progress-bar-empty">
<div id="unity-progress-bar-full"></div>
</div>
</div>
<div id="unity-warning"> </div>
<div id="unity-footer">
<div id="unity-webgl-logo"></div>
<div id="unity-fullscreen-button"></div>
<div id="unity-build-title">Platformer</div>
</div>
</div>
@section Scripts {
<link rel="shortcut icon" href="webgl-gzip/TemplateData/favicon.ico">
<link rel="stylesheet" href="webgl-gzip/TemplateData/style.css">
<script>
var container = document.querySelector("#unity-container");
var canvas = document.querySelector("#unity-canvas");
var loadingBar = document.querySelector("#unity-loading-bar");
var progressBarFull = document.querySelector("#unity-progress-bar-full");
var fullscreenButton = document.querySelector("#unity-fullscreen-button");
var warningBanner = document.querySelector("#unity-warning");
// 一時的なメッセージバナー/リボンを数秒間表示するか、
// type == 'error'の場合はキャンバスの上部に永続的なエラーメッセージを表示します。
// type == 'warning'の場合、黄色のハイライト色が使用されます。
// この関数を変更または削除して、重要ではない警告とエラーメッセージがユーザーに表示されるように
// 視覚的に表示される方法をカスタマイズします。
function unityShowBanner(msg, type) {
function updateBannerVisibility() {
warningBanner.style.display = warningBanner.children.length ? 'block' : 'none';
}
var div = document.createElement('div');
div.innerHTML = msg;
warningBanner.appendChild(div);
if (type == 'error') div.style = 'background: red; padding: 10px;';
else {
if (type == 'warning') div.style = 'background: yellow; padding: 10px;';
setTimeout(function() {
warningBanner.removeChild(div);
updateBannerVisibility();
}, 5000);
}
updateBannerVisibility();
}
var buildUrl = "webgl-gzip/Build";
var loaderUrl = buildUrl + "/WebGL_Gzip.loader.js";
var config = {
dataUrl: buildUrl + "/WebGL_Gzip.data.gz",
frameworkUrl: buildUrl + "/WebGL_Gzip.framework.js.gz",
codeUrl: buildUrl + "/WebGL_Gzip.wasm.gz",
streamingAssetsUrl: "StreamingAssets",
companyName: "DefaultCompany",
productName: "Platformer",
productVersion: "2.1.0",
showBanner: unityShowBanner,
};
// デフォルトでは、Unity は WebGL キャンバスレンダリングのターゲットサイズを
// キャンバス要素の DOM サイズ(window.devicePixelRatio でスケーリング)と一致させます。
// この同期がエンジン内で発生しないようにする場合は、これを false に設定し、
// 代わりにサイズを大きくします。 キャンバスの DOM サイズと WebGL は、
// ターゲットサイズを自分でレンダリングします。
// config.matchWebGLToCanvasSize = false;
if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
container.className = "unity-mobile";
// モバイルデバイスでフィルレートのパフォーマンスを低下させないようにし、
// モバイルブラウザで低 DPI モードをデフォルト/オーバーライドします。
config.devicePixelRatio = 1;
unityShowBanner('WebGL builds are not supported on mobile devices.');
} else {
canvas.style.width = "960px";
canvas.style.height = "600px";
}
loadingBar.style.display = "block";
var script = document.createElement("script");
script.src = loaderUrl;
script.onload = () => {
createUnityInstance(canvas, config, (progress) => {
progressBarFull.style.width = 100 * progress + "%";
}).then((unityInstance) => {
loadingBar.style.display = "none";
fullscreenButton.onclick = () => {
unityInstance.SetFullscreen(1);
};
}).catch((message) => {
alert(message);
});
};
document.body.appendChild(script);
</script>
}
Ubah suai untuk membenarkan navigasi ke Index.cshtml
halaman ini.
<!-- 省略 -->
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
<!-- 追加 -->
<ul>
<li><a href="index.html">index.html</a></li>
<li><a href="WebGL">WebGL</a></li>
<li><a href="WebGLGzip">WebGLGzip</a></li>
</ul>
Menetapkan Program.cs
app.UseStaticFiles
Ubah suai bahagian yang memproses kaedah seperti berikut.
Sebelum pembetulan
// ここから追加
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".data"] = "application/octet-stream";
provider.Mappings[".wasm"] = "application/wasm";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = provider,
});
// ここまで追加
Selepas pembetulan
// ここから追加
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".data"] = "application/octet-stream";
provider.Mappings[".wasm"] = "application/wasm";
provider.Mappings[".br"] = "application/octet-stream"; // .br ファイルにアクセスできるように追加
provider.Mappings[".js"] = "application/javascript"; // 後の変換の為に追加
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = provider,
OnPrepareResponse = context =>
{
var path = context.Context.Request.Path.Value;
var extension = Path.GetExtension(path);
// 「.gz」「.br」ファイルにアクセスした場合は Content-Type と Content-Encoding を設定する
if (extension == ".gz" || extension == ".br")
{
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path) ?? "";
if (provider.TryGetContentType(fileNameWithoutExtension, out string? contentType))
{
context.Context.Response.ContentType = contentType;
context.Context.Response.Headers.Add("Content-Encoding", extension == ".gz" ? "gzip" : "br");
}
}
},
});
// ここまで追加
Dalam ASP.NET Core .gz
, fail Content-Type
application/x-gzip
kembali dengan .
Oleh kerana itu, Unity WebGL pada pelanggan tidak dapat menentukannya, jadi .gz
saya menulis semula dan mengembalikannya mengikut Content-Type
pelanjutan fail yang tidak termasuk .
Content-Encoding
Saya juga menetapkannya kerana perlu gzip
.
Dengan cara ini, saya juga meletakkan kod Brotli bersama-sama, jadi anda boleh menggunakan kod ini seperti dalam surat-menyurat Brotli item seterusnya.
Brotli juga .br
menetapkan penulisan Content-Encoding
br
semula untuk dipadankan dengan Content-Type
pelanjutan fail tanpa .
Walau bagaimanapun, fail tidak boleh diakses secara lalai dalam ASP.NET Core,.br
jadi provider.Mappings
saya menambahnya dengan .br
.
Selepas itu, jalankan debug dan periksa sama ada permainan berfungsi dengan betul.
Jika anda telah menyediakannya dengan betul dan permainan masih tidak akan dipaparkan, cuba kosongkan cache pelayar web anda untuk mengosongkan kuki anda.
Menjalankan WebGL dimampatkan dengan Brotli
Prosedur ini hampir sama dengan Gzip, menggantikan bahagian Gzip dengan Brotli. Walau bagaimanapun, fail Brotli (.br) tidak boleh diakses secara lalai dalam ASP.NET Core. Anda perlu mengkonfigurasinya supaya anda boleh mengaksesnya, tetapi jika anda menggunakan kod pada masa Gzip, ia disokong.
Mula-mula, cipta penggunaan fail dan halaman WebGL.
Peletakan fail WebGL
wwwroot
webgl-brotli
Di bawah Buat folder, salin folder daripada fail WebGL yang Build
TemplateData
anda cipta dengan Brotli.
Buat Laman Pisau Cukur
Buat fail WebGLBrotli.cshtml
menggunakan langkah yang sama seperti Gzip.
Kod ini adalah seperti berikut dengan merujuk kepada Output dalam index.html
Perpaduan.
Laluan ini sepadan dengan folder yang anda buat webgl-brotli
sebelum ini untuk fail WebGL.
@page
@model UnityPublishWebglAspNetCore.Pages.WebGLBrotliModel
@{
}
<div id="unity-container" class="unity-desktop">
<canvas id="unity-canvas" width=960 height=600></canvas>
<div id="unity-loading-bar">
<div id="unity-logo"></div>
<div id="unity-progress-bar-empty">
<div id="unity-progress-bar-full"></div>
</div>
</div>
<div id="unity-warning"> </div>
<div id="unity-footer">
<div id="unity-webgl-logo"></div>
<div id="unity-fullscreen-button"></div>
<div id="unity-build-title">Platformer</div>
</div>
</div>
@section Scripts {
<link rel="shortcut icon" href="webgl-brotli/TemplateData/favicon.ico">
<link rel="stylesheet" href="webgl-brotli/TemplateData/style.css">
<script>
var container = document.querySelector("#unity-container");
var canvas = document.querySelector("#unity-canvas");
var loadingBar = document.querySelector("#unity-loading-bar");
var progressBarFull = document.querySelector("#unity-progress-bar-full");
var fullscreenButton = document.querySelector("#unity-fullscreen-button");
var warningBanner = document.querySelector("#unity-warning");
// 一時的なメッセージバナー/リボンを数秒間表示するか、
// type == 'error'の場合はキャンバスの上部に永続的なエラーメッセージを表示します。
// type == 'warning'の場合、黄色のハイライト色が使用されます。
// この関数を変更または削除して、重要ではない警告とエラーメッセージがユーザーに表示されるように
// 視覚的に表示される方法をカスタマイズします。
function unityShowBanner(msg, type) {
function updateBannerVisibility() {
warningBanner.style.display = warningBanner.children.length ? 'block' : 'none';
}
var div = document.createElement('div');
div.innerHTML = msg;
warningBanner.appendChild(div);
if (type == 'error') div.style = 'background: red; padding: 10px;';
else {
if (type == 'warning') div.style = 'background: yellow; padding: 10px;';
setTimeout(function() {
warningBanner.removeChild(div);
updateBannerVisibility();
}, 5000);
}
updateBannerVisibility();
}
var buildUrl = "webgl-brotli/Build";
var loaderUrl = buildUrl + "/WebGL_Brotli.loader.js";
var config = {
dataUrl: buildUrl + "/WebGL_Brotli.data.br",
frameworkUrl: buildUrl + "/WebGL_Brotli.framework.js.br",
codeUrl: buildUrl + "/WebGL_Brotli.wasm.br",
streamingAssetsUrl: "StreamingAssets",
companyName: "DefaultCompany",
productName: "Platformer",
productVersion: "2.1.0",
showBanner: unityShowBanner,
};
// デフォルトでは、Unity は WebGL キャンバスレンダリングのターゲットサイズを
// キャンバス要素の DOM サイズ(window.devicePixelRatio でスケーリング)と一致させます。
// この同期がエンジン内で発生しないようにする場合は、これを false に設定し、
// 代わりにサイズを大きくします。 キャンバスの DOM サイズと WebGL は、
// ターゲットサイズを自分でレンダリングします。
// config.matchWebGLToCanvasSize = false;
if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
container.className = "unity-mobile";
// モバイルデバイスでフィルレートのパフォーマンスを低下させないようにし、
// モバイルブラウザで低 DPI モードをデフォルト/オーバーライドします。
config.devicePixelRatio = 1;
unityShowBanner('WebGL builds are not supported on mobile devices.');
} else {
canvas.style.width = "960px";
canvas.style.height = "600px";
}
loadingBar.style.display = "block";
var script = document.createElement("script");
script.src = loaderUrl;
script.onload = () => {
createUnityInstance(canvas, config, (progress) => {
progressBarFull.style.width = 100 * progress + "%";
}).then((unityInstance) => {
loadingBar.style.display = "none";
fullscreenButton.onclick = () => {
unityInstance.SetFullscreen(1);
};
}).catch((message) => {
alert(message);
});
};
document.body.appendChild(script);
</script>
}
Ubah suai untuk membenarkan navigasi ke Index.cshtml
halaman ini.
<!-- 省略 -->
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
<!-- 追加 -->
<ul>
<li><a href="index.html">index.html</a></li>
<li><a href="WebGL">WebGL</a></li>
<li><a href="WebGLGzip">WebGLGzip</a></li>
<li><a href="WebGLBrotli">WebGLBrotli</a></li>
</ul>
Menetapkan Program.cs
Jika anda mengubahnya apabila Gzip disokong, anda boleh menggunakan kod yang sama.
Selepas membetulkannya, jalankan debug dan semak sama ada permainan berfungsi.
Jika anda telah menyediakannya dengan betul dan permainan masih tidak akan dipaparkan, cuba kosongkan cache pelayar web anda untuk mengosongkan kuki anda.
Memahami gejala Mengakses Fail Brotli pada Pelayan Web IIS
Brotli tidak disokong oleh IIS secara lalai, jadi konfigurasi pada bahagian IIS diperlukan. Nampaknya ia boleh dikendalikan dengan membuat tetapan lanjutan, tetapi saya tidak akan menerangkannya dalam petua ini. Sila rujuk maklumat yang dipautkan di bawah.
- asp.net teras 2.2 mampatan brotli tidak berfungsi pada IIS?
- Gambaran Keseluruhan Mampatan IIS
- WebGL: Sampel Kod Konfigurasi Pelayan
- WebGL - Menggunakan Binaan Mampat
Mesej ralat
Unable to load file webgl-brotli/Build/WebGL_Brotli.framework.js.br! Check that the file exists on the remote server. (also check browser Console and Devtools Network tab to debug)