Rularea Unity WebGL cu ASP.NET Core
Mediul de verificare
- Windows
-
- Ferestre 11
- Unity Editor
-
- 2020.3.25F1
- Visual Studio
-
- Visual Studio 2022
- ASP.NET Nucleul
-
- ASP.NET Core 6.0
- Internet Information Services (IIS)
-
- IIS 10.0
La început
Aflați cum să rulați o ieșire de joc ca WebGL în Unity pe un server web care rulează ASP.NET Core. Pentru programele de joc, utilizați cele rezultate în pașii de sfaturi de mai jos. Exemplul jocului folosește 2D Platformer Microgame, care poate fi creat din Unity Hub.
Voi explica cum să configurați "WebGL necomprimat", "WebGL comprimat cu Gzip" și "WebGL comprimat cu Brotli" pentru a rula jocuri WebGL. Procedura este aceeași pentru toți.
Folosim Visual Studio 2022 ASP.NET Core 6.0, dar versiunile mai vechi vor funcționa probabil. Cu toate acestea, structura codului inițial este diferită pentru fiecare versiune, așa că vă rugăm să înțelegeți singuri diferențele.
Crearea unui ASP.NET proiect de bază
Lansați "Visual Studio 2022" din meniul Start.
Selectați Creare proiect nou.
De data aceasta, selectați "ASP.NET Core Web App" ca eșantion. Dacă rulați pe ASP.NET Core, puteți rula alte șabloane, dar va trebui să urmați fiecare șablon pentru a-l construi.
Setați numele și locația proiectului în mod arbitrar.
Lăsați informațiile suplimentare așa cum sunt.
Proiectul a fost creat.
Rulați WebGL necomprimat
Pregătiți un program WebGL creat fără compresie.
Asigurați-vă că jocul funcționează rapid
ASP.NET Încercați să rulați un joc WebGL cu mai puține setări fără a urma eticheta Core.
În ASP.NET Core, nu puteți accesa unele fișiere WebGL emise de Unity în starea implicită. Faceți acest lucru accesibil.
Programul.cs
Deschideți din proiectul dvs Program.cs
. Se aplică versiunilor Startup.cs
anterioare ASP.NET Core .
Adăugați un spațiu de nume în partea de sus a codului și înlocuiți următoarele în cod 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
, astfel încât atunci când un fișier este accesat, .wasm
acesta poate fi returnat clientului cu .Content-Type
Implementare WebGL
Plasați următoarele foldere de fișiere din Unity în proiectul wwwroot
dvs.
- Index.html
- Zidi
- TemplateData
Index.cshtml
index.html
Deschideți linkul pentru a-l putea accesa.
<!-- 省略 -->
<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>
Rulați programul și asigurați-vă că jocul funcționează.
Rulați un program WebGL pe o pagină Razor
Jocul anterior a rulat pe un fișier HTML static, deci rulează într-un loc care nu are nimic de-a face cu ASP.NET Core. Nu este foarte de dorit pentru uniformitatea programului, așa că vom muta comportamentul fișierului HTML în Razor Pages.
Faceți clic dreapta pe folderul Pagini din proiect pentru a adăuga un element nou.
Selectați Razor Page - Empty. Nu este specificat un nume special, dar este adăugat aici WebGL.cshtml
.
Codul este afișat.
index.html
Consultați conținutul fișierului și portați la WebGL.cshtml
.
link
Există câteva puncte ciudate, cum ar fi modul de plasare a etichetei, dar o voi lăsa așa cum este de dragul simplității explicației.
@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
Adăugați un link la .
<!-- 省略 -->
<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>
Încercați să rulați programul. Puteți vedea că antetul și subsolul _Layout.cshtml
sunt afișate pe pagina WebGL în conformitate cu .
Modificarea locației fișierelor WebGL
Am plasat fișierul WebGL direct sub , dar această metodă îl va suprascrie atunci când plasați două sau mai multe fișiere WebGL wwwroot
.
Voi explica cum să puneți acest lucru în foldere separate și să îl mutați.
În primul rând, creați un folder nou numit "webgl" și mutați-l acolo. Cele două foldere care trebuie Build
mutate sunt , TemplateData
.
index.html
L-am portat deja pe Razor Pages și îl pot șterge în siguranță.
Deoarece WebGL.cshtml
am aprofundat ierarhia folderelor, vom aprofunda și calea descrisă în . Corecția este de 3 linii.
Înainte de corectare
<link rel="shortcut icon" href="TemplateData/favicon.ico">
<link rel="stylesheet" href="TemplateData/style.css">
var buildUrl = "Build";
După corectare
<link rel="shortcut icon" href="webgl/TemplateData/favicon.ico">
<link rel="stylesheet" href="webgl/TemplateData/style.css">
var buildUrl = "webgl/Build";
Rulați programul pentru a vedea dacă funcționează corect.
Rularea WebGL comprimat cu Gzip
Extensia fișierului comprimat de Gzip este .gz
, și este un fișier care poate fi gestionat de ASP.NET Core,
Unity WebGL Content-Type
și sunt tratate diferit și necesită conversie.
Mai întâi, creați o implementare și o pagină de fișiere WebGL.
Plasarea fișierelor WebGL
wwwroot
webgl-gzip
Creați un folder sub Gzip și copiați folderul , din fișierul Build
TemplateData
WebGL pe care l-ați creat cu Gzip.
Creați o pagină de ras
De data WebGLGzip.cshtml
aceasta, creați fișierul utilizând aceeași procedură ca atunci când nu este comprimat.
Codul este după cum urmează, cu referire la Output in index.html
Unity.
Calea se potrivește cu folderul pe care l-ați creat webgl-gzip
anterior pentru fișierele 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>
}
Modificați pentru a permite navigarea la Index.cshtml
această pagină.
<!-- 省略 -->
<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>
Program de fixare.cs
app.UseStaticFiles
Modificați partea care procesează metoda după cum urmează.
Înainte de corectare
// ここから追加
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".data"] = "application/octet-stream";
provider.Mappings[".wasm"] = "application/wasm";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = provider,
});
// ここまで追加
După corectare
// ここから追加
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");
}
}
},
});
// ここまで追加
În ASP.NET Core .gz
, fișierul Content-Type
application/x-gzip
revine cu .
Așa cum este, Unity WebGL pe client nu îl poate determina, așa .gz
că îl rescriu și îl returnez în funcție Content-Type
de extensia fișierului care exclude .
Content-Encoding
De asemenea, l-am setat gzip
pentru că este necesar.
Apropo, am pus și codul Brotli împreună, astfel încât să puteți utiliza acest cod așa cum este în corespondența Brotli a următorului articol.
Brotli setează, de asemenea, .br
rescrierea Content-Encoding
br
pentru a se potrivi cu Content-Type
extensia fișierului fără .
Cu toate acestea, fișierul este inaccesibil în mod implicit în ASP.NET Core,.br
așa că provider.Mappings
l-am adăugat cu .br
.
După aceea, rulați depanarea și verificați dacă jocul funcționează corect.
Dacă l-ați configurat corect și jocul tot nu se afișează, încercați să goliți memoria cache a browserului web pentru a șterge cookie-urile.
Rularea WebGL comprimat cu Brotli
Procedura este aproape aceeași cu Gzip, înlocuind partea Gzip cu Brotli. Cu toate acestea, fișierele Brotli (.br) nu sunt accesibile în mod implicit în ASP.NET Core. Trebuie să îl configurați astfel încât să îl puteți accesa, dar dacă utilizați codul în momentul Gzip, acesta este acceptat.
Mai întâi, creați o implementare și o pagină de fișiere WebGL.
Plasarea fișierelor WebGL
wwwroot
webgl-brotli
Sub Creare folder, copiați folderul , din Build
TemplateData
fișierul WebGL pe care l-ați creat cu Brotli.
Creați o pagină de ras
Creați fișierul utilizând WebGLBrotli.cshtml
aceiași pași ca și pentru Gzip.
Codul este după cum urmează, cu referire la Output in index.html
Unity.
Calea se potrivește cu folderul pe care l-ați creat webgl-brotli
anterior pentru fișierele 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>
}
Modificați pentru a permite navigarea la Index.cshtml
această pagină.
<!-- 省略 -->
<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>
Program de fixare.cs
Dacă îl modificați atunci când este acceptat Gzip, puteți utiliza același cod.
După remedierea acestuia, rulați depanarea și verificați dacă jocul funcționează.
Dacă l-ați configurat corect și jocul tot nu se afișează, încercați să goliți memoria cache a browserului web pentru a șterge cookie-urile.
Înțelegerea simptomelor de accesare a fișierelor Brotli pe un server web IIS
Brotli nu este acceptat de IIS în mod implicit, deci este necesară configurarea pe partea IIS. Se pare că poate fi gestionat făcând setări avansate, dar nu o voi explica în acest sfat. Vă rugăm să consultați informațiile legate mai jos.
- asp.net compresie core 2.2 brotli nu funcționează pe IIS?
- Prezentare generală a compresiei IIS
- WebGL: Exemplu de cod de configurare a serverului
- WebGL - Implementarea compilărilor comprimate
Mesaj de eroare
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)