Uruchamianie Unity WebGL z ASP.NET Core
Środowisko weryfikacji
- Windows
-
- Okna 11
- Edytor Unity
-
- 2020.3.25f1
- Visual Studio
-
- Visual Studio 2022
- ASP.NET Rdzeń
-
- ASP.NET Core 6.0
- Internetowe usługi informacyjne (IIS)
-
- Usługi IIS 10.0
Na początku
Dowiedz się, jak uruchomić dane wyjściowe gry jako WebGL w Unity na serwerze internetowym z systemem ASP.NET Core. W przypadku programów do gier użyj tych danych wyjściowych w poniższych krokach wskazówek. Przykład gry wykorzystuje mikrogrę platformową 2D, którą można utworzyć z poziomu Unity Hub.
Wyjaśnię, jak skonfigurować "Uncompressed WebGL", "WebGL compressed with Gzip" i "WebGL compressed with Brotli" do uruchamiania gier WebGL. Procedura jest taka sama dla wszystkich.
Używamy programu Visual Studio 2022 ASP.NET Core 6.0, ale starsze wersje prawdopodobnie będą działać. Jednak struktura początkowego kodu jest inna dla każdej wersji, więc proszę sam zrozumieć różnice.
Tworzenie projektu ASP.NET Core
Uruchom "Visual Studio 2022" z menu Start.
Wybierz pozycję Utwórz nowy projekt.
Tym razem wybierz "ASP.NET Core Web App" jako przykład. Jeśli korzystasz z ASP.NET Core, możesz uruchamiać inne szablony, ale musisz przestrzegać każdego szablonu, aby dowiedzieć się, jak go skompilować.
Ustaw nazwę i lokalizację projektu dowolnie.
Pozostaw dodatkowe informacje bez zmian.
Projekt został stworzony.
Uruchamianie nieskompresowanego WebGL
Przygotuj program WebGL utworzony bez kompresji.
Upewnij się, że gra działa szybko
ASP.NET Spróbuj uruchomić grę WebGL z mniejszą liczbą ustawień bez przestrzegania podstawowej etykiety.
W ASP.NET Core nie można uzyskać dostępu do niektórych plików WebGL emitowanych przez Unity w stanie domyślnym. Udostępnij to.
Program.cs
Otwórz z poziomu projektu Program.cs
. Dotyczy wcześniejszych wersji Startup.cs
ASP.NET Core.
Dodaj przestrzeń nazw na początku kodu i zastąp następujący tekst w kodzie 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
, dzięki czemu po uzyskaniu dostępu .wasm
do pliku można go zwrócić klientowi z określonym Content-Type
formatem .
Wdrażanie WebGL
Umieść następujące foldery plików z Unity w swoim projekcie wwwroot
.
- indeks.html
- Budować
- TemplateData
Index.cshtml
index.html
Otwórz łącze, aby uzyskać do niego dostęp.
<!-- 省略 -->
<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>
Uruchom program i upewnij się, że gra działa.
Uruchamianie programu WebGL na stronie Razor
Poprzednia gra działała na statycznym pliku HTML, więc działa w miejscu, które nie ma nic wspólnego z ASP.NET Core. Nie jest to zbyt pożądane dla jednolitości programu, więc przeniesiemy zachowanie pliku HTML do Razor Pages.
Kliknij prawym przyciskiem myszy folder Strony w projekcie, aby dodać nowy element.
Wybierz Razor Page - Empty. Nie ma określonej nazwy, ale jest ona tutaj dodawana WebGL.cshtml
.
Kod zostanie wyświetlony.
index.html
Zapoznaj się z zawartością pliku i port do WebGL.cshtml
.
link
Jest kilka dziwnych punktów, takich jak sposób umieszczania tagu, ale zostawię to tak, jak jest, ze względu na prostotę wyjaśnienia.
@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
Dodaj łącze do programu .
<!-- 省略 -->
<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>
Spróbuj uruchomić program. Widać, że nagłówek i stopka _Layout.cshtml
są wyświetlane na stronie WebGL zgodnie z .
Zmiana lokalizacji plików WebGL
Umieściłem plik WebGL bezpośrednio pod , ale ta metoda zastąpi go po umieszczeniu dwóch lub więcej plików WebGL wwwroot
.
Wyjaśnię, jak umieścić to w osobnych folderach i przenieść.
Przede wszystkim utwórz nowy folder o nazwie "webgl" i przenieś go tam. Dwa foldery do Build
przeniesienia to , TemplateData
.
index.html
Przeniosłem go już na strony Razor i mogę go bezpiecznie usunąć.
Ponieważ WebGL.cshtml
pogłębiliśmy hierarchię folderów, pogłębimy również ścieżkę opisaną w programie . Korekta wynosi 3 linie.
Przed korektą
<link rel="shortcut icon" href="TemplateData/favicon.ico">
<link rel="stylesheet" href="TemplateData/style.css">
var buildUrl = "Build";
Po korekcie
<link rel="shortcut icon" href="webgl/TemplateData/favicon.ico">
<link rel="stylesheet" href="webgl/TemplateData/style.css">
var buildUrl = "webgl/Build";
Uruchom program, aby sprawdzić, czy działa poprawnie.
Uruchamianie WebGL skompresowanego za pomocą Gzip
Rozszerzenie pliku skompresowanego przez Gzip to , i jest to .gz
plik, który może być obsługiwany przez ASP.NET Core,
Unity WebGL Content-Type
i są obsługiwane inaczej i wymagają konwersji.
Najpierw utwórz wdrożenie pliku WebGL i stronę.
Umieszczanie plików WebGL
wwwroot
webgl-gzip
Utwórz folder w obszarze Gzip i skopiuj go z pliku WebGL utworzonego za pomocą programu Build
TemplateData
Gzip.
Tworzenie strony Razor
Tym razem WebGLGzip.cshtml
utwórz plik przy użyciu tej samej procedury, co w przypadku dekompresji.
Kod jest następujący w odniesieniu do Output in index.html
Unity.
Ścieżka odpowiada folderowi utworzonemu webgl-gzip
wcześniej dla plików 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>
}
Zmodyfikuj, aby umożliwić nawigację do Index.cshtml
tej strony.
<!-- 省略 -->
<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 naprawczy.cs
app.UseStaticFiles
Zmodyfikuj część, która przetwarza metodę w następujący sposób.
Przed korektą
// ここから追加
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".data"] = "application/octet-stream";
provider.Mappings[".wasm"] = "application/wasm";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = provider,
});
// ここまで追加
Po korekcie
// ここから追加
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");
}
}
},
});
// ここまで追加
W programie ASP.NET Core .gz
plik Content-Type
application/x-gzip
powraca z rozszerzeniem .
Tak jak jest, Unity WebGL na kliencie nie może tego określić, więc .gz
przepisuję i zwracam go zgodnie z Content-Type
rozszerzeniem pliku, który wyklucza .
Content-Encoding
Ustawiam go również dlatego, że jest to gzip
konieczne.
Nawiasem mówiąc, złożyłem również kod Brotli, abyś mógł użyć tego kodu, tak jak jest w korespondencji Brotli następnego elementu.
Brotli ustawia również .br
przepisywanie Content-Encoding
br
, aby dopasować Content-Type
rozszerzenie pliku bez .
Jednak plik jest domyślnie niedostępny w ASP.NET Core,.br
więc provider.Mappings
dodałem go za pomocą .br
.
Następnie uruchom debugowanie i sprawdź, czy gra działa poprawnie.
Jeśli gra została poprawnie skonfigurowana, spróbuj wyczyścić pamięć podręczną przeglądarki, aby wyczyścić pliki cookie.
Uruchamianie WebGL skompresowanego za pomocą Brotli
Procedura jest prawie taka sama jak Gzip, zastępując część Gzip Brotli. Jednak pliki Brotli (.br) nie są domyślnie dostępne w ASP.NET Core. Musisz go skonfigurować tak, aby mieć do niego dostęp, ale jeśli używasz kodu w czasie Gzip, jest on obsługiwany.
Najpierw utwórz wdrożenie pliku WebGL i stronę.
Umieszczanie plików WebGL
wwwroot
webgl-brotli
W obszarze Utwórz folder skopiuj folder , z Build
TemplateData
pliku WebGL utworzonego za pomocą programu Brotli.
Tworzenie strony Razor
Utwórz plik, wykonując WebGLBrotli.cshtml
te same kroki, co w przypadku Gzip.
Kod jest następujący w odniesieniu do Output in index.html
Unity.
Ścieżka odpowiada folderowi utworzonemu webgl-brotli
wcześniej dla plików 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>
}
Zmodyfikuj, aby umożliwić nawigację do Index.cshtml
tej strony.
<!-- 省略 -->
<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 naprawczy.cs
Jeśli zmodyfikujesz go, gdy Gzip jest obsługiwany, możesz użyć tego samego kodu.
Po naprawieniu uruchom debugowanie i sprawdź, czy gra działa.
Jeśli gra została poprawnie skonfigurowana, spróbuj wyczyścić pamięć podręczną przeglądarki, aby wyczyścić pliki cookie.
Opis symptomów uzyskiwania dostępu do plików Brotli na serwerze sieci Web usług IIS
Brotli nie jest domyślnie obsługiwany przez IIS, więc wymagana jest konfiguracja po stronie IIS. Wydaje się, że można sobie z tym poradzić, wprowadzając zaawansowane ustawienia, ale nie wyjaśnię tego w tej wskazówce. Zapoznaj się z poniższymi informacjami.
- asp.net kompresja brotli core 2.2 nie działa na IIS?
- Omówienie kompresji usług IIS
- WebGL: Przykładowy kod konfiguracji serwera
- WebGL — wdrażanie skompresowanych kompilacji
Komunikat o błędzie
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)