Kører Unity WebGL med ASP.NET Core
Miljø til bekræftelse
- Windows
-
- Windows 11
- Enhedslistens redaktør
-
- 2020.3.25f1
- Visual Studio
-
- Visual Studio 2022
- ASP.NET kerne
-
- ASP.NET Core 6.0
- IIS (Internet Information Services)
-
- IIS 10.0
Først
Få mere at vide om, hvordan du kører et spiloutput som WebGL i Unity på en webserver, der kører ASP.NET Core. For spilprogrammer skal du bruge dem, der er output i nedenstående tiptrin. Spileksemplet bruger 2D Platformer Microgame, som kan oprettes fra Unity Hub.
Jeg vil forklare, hvordan du konfigurerer "Ukomprimeret WebGL", "WebGL komprimeret med Gzip" og "WebGL komprimeret med Brotli" for at køre WebGL-spil. Proceduren er den samme for dem alle.
Vi bruger Visual Studio 2022, ASP.NET Core 6.0, men ældre versioner vil sandsynligvis fungere. Strukturen af den oprindelige kode er dog forskellig for hver version, så forstå venligst forskellene selv.
Oprettelse af et ASP.NET kerneprojekt
Start "Visual Studio 2022" fra startmenuen.
Vælg Opret nyt projekt.
Denne gang skal du vælge "ASP.NET Core Web App" som et eksempel. Hvis du kører på ASP.NET Core, kan du køre andre skabeloner, men du skal følge hver skabelon om, hvordan du bygger den.
Indstil projektnavnet og placeringen vilkårligt.
Lad de yderligere oplysninger være, som de er.
Projektet er oprettet.
Kør ukomprimeret WebGL
Forbered et WebGL-program oprettet uden komprimering.
Sørg for, at spillet fungerer hurtigt
ASP.NET Prøv at køre et WebGL-spil med færre indstillinger uden at følge Core-etikette.
I ASP.NET Core kan du ikke få adgang til nogle WebGL-filer, der udsendes af Unity i standardtilstanden. Gør dette tilgængeligt.
Program.cs
Åbn fra dit Program.cs
projekt. Gælder for tidligere ASP.NET Core-versioner Startup.cs
.
Tilføj et navneområde øverst i koden, og erstat følgende i koden 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
, så når en fil åbnes, .wasm
kan den returneres til klienten med den angivne Content-Type
.
WebGL-implementering
Placer følgende filmapper fra Unity i dit projekt wwwroot
.
- indeks.html
- Bygge
- TemplateData
Index.cshtml
index.html
Åbn linket, så du kan få adgang til det.
<!-- 省略 -->
<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>
Kør programmet og sørg for, at spillet fungerer.
Kør et WebGL-program på en Razor-side
Det forrige spil kørte på en statisk HTML-fil, så det kører et sted, der ikke har noget at gøre med ASP.NET Core. Det er ikke særlig ønskeligt for programmets ensartethed, så vi flytter HTML-filens opførsel til Razor Pages.
Højreklik på mappen Pages i projektet for at tilføje et nyt element.
Vælg Barberbladsside - Tom. Der er ikke angivet noget bestemt navn, men det tilføjes her WebGL.cshtml
.
Koden vises.
index.html
Se indholdet af filen og porten til WebGL.cshtml
.
link
Der er nogle mærkelige punkter, såsom hvordan man placerer mærket, men jeg vil lade det være som det er af hensyn til enkelhed i forklaringen.
@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
Føj et link til .
<!-- 省略 -->
<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>
Prøv at køre programmet. Du kan se, at sidehovedet og sidefoden _Layout.cshtml
vises på WebGL-siden i henhold til .
Skift placeringen af WebGL-filer
Jeg placerede WebGL-filen direkte under , men denne metode overskriver den, når du placerer to eller flere WebGL-filer wwwroot
.
Jeg forklarer, hvordan du sætter dette i separate mapper og flytter det.
Først og fremmest skal du oprette en ny mappe kaldet "webgl" og flytte den der. De to mapper, der Build
skal flyttes, er , TemplateData
.
index.html
Jeg har allerede porteret det til Razor Pages og kan sikkert slette det.
Da WebGL.cshtml
vi har uddybet mappehierarkiet, vil vi også uddybe stien beskrevet i . Korrektionen er 3 linjer.
Før korrektion
<link rel="shortcut icon" href="TemplateData/favicon.ico">
<link rel="stylesheet" href="TemplateData/style.css">
var buildUrl = "Build";
Efter korrektion
<link rel="shortcut icon" href="webgl/TemplateData/favicon.ico">
<link rel="stylesheet" href="webgl/TemplateData/style.css">
var buildUrl = "webgl/Build";
Kør programmet for at se, om det fungerer korrekt.
Kører WebGL komprimeret med Gzip
Udvidelsen af filen komprimeret af Gzip er , og det er .gz
en fil, der kan håndteres af ASP.NET Core,
Unity WebGL Content-Type
og håndteres anderledes og kræver konvertering.
Opret først en WebGL-filinstallation og -side.
WebGL filplacering
wwwroot
webgl-gzip
Opret en mappe under Gzip, og kopiér mappen , fra den WebGL-filBuild
TemplateData
, du oprettede med Gzip.
Opret en barberbladsside
Denne gang WebGLGzip.cshtml
skal du oprette filen ved hjælp af samme procedure som ved ukomprimeret.
Koden er som følger med henvisning til Output in index.html
Unity.
Stien svarer til den mappe, du oprettede webgl-gzip
tidligere til WebGL-filerne.
@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>
}
Rediger for at tillade navigation til Index.cshtml
denne side.
<!-- 省略 -->
<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>
Reparation af program.cs
app.UseStaticFiles
Rediger den del, der behandler metoden, som følger.
Før korrektion
// ここから追加
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".data"] = "application/octet-stream";
provider.Mappings[".wasm"] = "application/wasm";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = provider,
});
// ここまで追加
Efter korrektion
// ここから追加
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");
}
}
},
});
// ここまで追加
I ASP.NET Core .gz
vender filen Content-Type
application/x-gzip
tilbage med .
Som det er, kan Unity WebGL på klienten ikke bestemme det, så .gz
jeg omskriver og returnerer det i henhold til Content-Type
udvidelsen af filen, der udelukker .
Content-Encoding
Jeg indstiller det også, fordi det gzip
er nødvendigt.
Forresten sætter jeg også Brotli-koden sammen, så du kan bruge denne kode, som den er i Brotli-korrespondancen i næste punkt.
Brotli indstiller også .br
omskrivning Content-Encoding
br
for at matche Content-Type
udvidelsen af filen uden .
Filen er dog som standard utilgængelig i ASP.NET Core,.br
så provider.Mappings
jeg tilføjede den med .br
.
Kør derefter fejlretningen og kontroller, om spillet fungerer korrekt.
Hvis du har konfigureret det korrekt, og spillet stadig ikke vises, kan du prøve at rydde din webbrowsers cache for at rydde dine cookies.
Kører WebGL komprimeret med Brotli
Proceduren er næsten den samme som Gzip, der erstatter Gzip-delen med Brotli. Brotli-filer (.br) er dog ikke tilgængelige som standard i ASP.NET Core. Du skal konfigurere det, så du kan få adgang til det, men hvis du bruger koden på tidspunktet for Gzip, understøttes den.
Opret først en WebGL-filinstallation og -side.
WebGL filplacering
wwwroot
webgl-brotli
Under Opret en mappe skal du kopiere mappen , fra den Build
TemplateData
WebGL-fil, du oprettede med Brotli.
Opret en barberbladsside
Opret filen ved hjælp af WebGLBrotli.cshtml
de samme trin som for Gzip.
Koden er som følger med henvisning til Output in index.html
Unity.
Stien svarer til den mappe, du oprettede webgl-brotli
tidligere til WebGL-filerne.
@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>
}
Rediger for at tillade navigation til Index.cshtml
denne side.
<!-- 省略 -->
<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>
Reparation af program.cs
Hvis du ændrer det, når Gzip understøttes, kan du bruge den samme kode.
Når du har rettet det, skal du køre debug og kontrollere, om spillet fungerer.
Hvis du har konfigureret det korrekt, og spillet stadig ikke vises, kan du prøve at rydde din webbrowsers cache for at rydde dine cookies.
Forstå symptomerne på adgang til Brotli-filer på en IIS-webserver
Brotli understøttes ikke af IIS som standard, så konfiguration på IIS-siden er påkrævet. Det ser ud til, at det kan håndteres ved at foretage avancerede indstillinger, men jeg vil ikke forklare det i dette tip. Se venligst de oplysninger, der er linket nedenfor.
- asp.net core 2.2 brotli-komprimering ikke på IIS?
- Oversigt over IIS-komprimering
- WebGL: Eksempel på serverkonfigurationskode
- WebGL - Implementering af komprimerede builds
Fejlmeddelelse
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)