Изпълнение на Unity WebGL с ASP.NET ядро
Среда за проверка
- Уиндоус
-
- Прозорци 11
- Редактор на единство
-
- 2020.3.25ф1
- Визуално студио
-
- Визуално студио 2022
- ASP.NET Ядро
-
- ASP.NET Ядро 6.0
- Интернет информационни услуги (IIS)
-
- ИИС 10.0
Отначало
Научете как да стартирате изход от игра като WebGL в Unity на уеб сървър, работещ ASP.NET Core. За програми за игри, използвайте тези, които се извеждат в стъпките със съвети по-долу. Примерът на играта използва 2D Platformer Microgame, който може да бъде създаден от Unity Hub.
Ще обясня как да настроите "Uncompressed WebGL", "WebGL компресиран с Gzip" и "WebGL компресиран с Brotli", за да стартирате WebGL игри. Процедурата е еднаква за всички тях.
Използваме Visual Studio 2022, ASP.NET Core 6.0, но по-старите версии вероятно ще работят. Структурата на първоначалния код обаче е различна за всяка версия, така че моля, разберете разликите сами.
Създаване на ASP.NET основен проект
Стартирайте "Visual Studio 2022" от стартовото меню.
Изберете Създаване на нов проект.
Този път изберете "ASP.NET Core Web App" като образец. Ако работите на ASP.NET Core, можете да изпълнявате други шаблони, но ще трябва да следвате всеки шаблон за това как да го изградите.
Задайте името и местоположението на проекта произволно.
Оставете допълнителната информация такава, каквато е.
Проектът е създаден.
Изпълнение на некомпресиран WebGL
Подгответе WebGL програма, създадена без компресия.
Уверете се, че играта работи бързо
ASP.NET Опитайте да стартирате WebGL игра с по-малко настройки, без да следвате етикета на ядрото.
В ASP.NET Core нямате достъп до някои WebGL файлове, излъчвани от Unity в състоянието по подразбиране. Направете това достъпно.
Програма.cs
Отворете от вашия Program.cs
проект. Отнася се за по-ранни ASP.NET основни версии Startup.cs
.
Добавете пространство на имената в горната част на кода и заменете следното в кода 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
, така че когато се осъществи достъп до даден файл, .wasm
той да може да бъде върнат на клиента с указания Content-Type
.
Разполагане на WebGL
Поставете следните папки с файлове от Unity във вашия проект wwwroot
.
- индекс.html
- Строя
- Данни за шаблон
Index.cshtml
index.html
Отворете връзката, за да имате достъп до нея.
<!-- 省略 -->
<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>
Стартирайте програмата и се уверете, че играта работи.
Изпълнение на програма WebGL на страница на Razor
Предишната игра се изпълняваше на статичен HTML файл, така че работи на място, което няма нищо общо с ASP.NET Core. Това не е много желателно за еднородност на програмата, така че ще преместим поведението на HTML файла в Razor Pages.
Щракнете с десния бутон върху папката Страници от вашия проект, за да добавите нов елемент.
Изберете Страница за бръснач - празна. Не е посочено конкретно име, но е добавено тук WebGL.cshtml
.
Кодът се показва.
index.html
Вижте съдържанието на файла и порта към WebGL.cshtml
.
link
Има някои странни моменти, като например как да поставите етикета, но ще го оставя такъв, какъвто е, за да се улесни обяснението.
@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
Добавяне на връзка към .
<!-- 省略 -->
<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>
Опитайте се да изпълните програмата. Можете да видите, че горният и долният колонтитул _Layout.cshtml
се показват на страницата WebGL според .
Промяна на местоположението на WebGL файлове
Поставих файла WebGL директно под , но този метод ще го презапише, когато поставите два или повече WebGL wwwroot
файла.
Ще обясня как да сложа това в отделни папки и да го преместя.
На първо място, създайте нова папка, наречена "webgl" и я преместете там. Двете папки, които трябва да Build
бъдат преместени, са , TemplateData
.
index.html
Вече го пренесох в Razor Pages и мога спокойно да го изтрия.
Тъй като WebGL.cshtml
сме задълбочили йерархията на папките, ще задълбочим и пътя, описан в . Корекцията е 3 реда.
Преди корекцията
<link rel="shortcut icon" href="TemplateData/favicon.ico">
<link rel="stylesheet" href="TemplateData/style.css">
var buildUrl = "Build";
След корекция
<link rel="shortcut icon" href="webgl/TemplateData/favicon.ico">
<link rel="stylesheet" href="webgl/TemplateData/style.css">
var buildUrl = "webgl/Build";
Стартирайте програмата, за да видите дали работи правилно.
Изпълнение на WebGL компресиран с Gzip
Разширението на файла, компресиран от Gzip е , и това е .gz
файл, който може да се обработва от ASP.NET Core,
Unity WebGL Content-Type
и се обработват по различен начин и изискват преобразуване.
Първо, създайте разполагане на WebGL файл и страница.
Разположение на WebGL файлове
wwwroot
webgl-gzip
Създайте папка под Gzip и копирайте папката , от WebGL файлаBuild
TemplateData
, който създадохте с Gzip.
Създаване на страница за бръснене
Този път WebGLGzip.cshtml
създайте файла, като използвате същата процедура, както когато не е компресиран.
Кодът е следният по отношение на изхода в index.html
единство.
Пътят съвпада с папката, която създадохте webgl-gzip
по-рано за 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>
}
Модифицирай, за да разрешиш навигация до Index.cshtml
тази страница.
<!-- 省略 -->
<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>
Програма за фиксиране.cs
app.UseStaticFiles
Променете частта, която обработва метода, както следва.
Преди корекцията
// ここから追加
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".data"] = "application/octet-stream";
provider.Mappings[".wasm"] = "application/wasm";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = provider,
});
// ここまで追加
След корекция
// ここから追加
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");
}
}
},
});
// ここまで追加
В ASP.NET Core .gz
файлът Content-Type
application/x-gzip
се връща с .
Както е, Unity WebGL на клиента не може да Content-Type
го определи, така че .gz
аз пренаписвам и го връщам според разширението на файла, което изключва .
Content-Encoding
Аз също го поставям, gzip
защото е необходимо.
Между другото, аз също сложих кода на Бротли заедно, така че можете да използвате този код, както е в кореспонденцията на Бротли на следващия елемент.
Brotli също задава .br
пренаписване Content-Encoding
br
, за да съответства Content-Type
на разширението на файла без .
Файлът обаче е недостъпен по подразбиране в ASP.NET Core,.br
затова provider.Mappings
го добавих с .br
.
След това стартирайте отстраняването на грешки и проверете дали играта работи правилно.
Ако сте го настроили правилно и играта все още няма да се показва, опитайте да изчистите кеша на уеб браузъра си, за да изчистите бисквитките.
Изпълнение на WebGL компресиран с Brotli
Процедурата е почти същата като Gzip, заменяйки Gzip частта с Brotli. Файловете Brotli (.br) обаче не са достъпни по подразбиране в ASP.NET Core. Трябва да го конфигурирате така, че да имате достъп до него, но ако използвате кода по време на Gzip, той се поддържа.
Първо, създайте разполагане на WebGL файл и страница.
Разположение на WebGL файлове
wwwroot
webgl-brotli
Под Създаване на папка копирайте папката Build
TemplateData
от WebGL файла, който създадохте с Brotli.
Създаване на страница за бръснене
Създайте файла, като използвате същите стъпки като WebGLBrotli.cshtml
за Gzip.
Кодът е следният по отношение на изхода в index.html
единство.
Пътят съвпада с папката, която създадохте webgl-brotli
по-рано за 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>
}
Модифицирай, за да разрешиш навигация до Index.cshtml
тази страница.
<!-- 省略 -->
<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>
Програма за фиксиране.cs
Ако го промените, когато се поддържа Gzip, можете да използвате същия код.
След като го поправите, стартирайте отстраняване на грешки и проверете дали играта работи.
Ако сте го настроили правилно и играта все още няма да се показва, опитайте да изчистите кеша на уеб браузъра си, за да изчистите бисквитките.
Разбиране на симптомите на достъп до файлове на Brotli на IIS уеб сървър
Brotli не се поддържа от IIS по подразбиране, така че се изисква конфигурация от страна на IIS. Изглежда, че може да се борави с него, като се направят разширени настройки, но няма да го обяснявам в този съвет. Моля, вижте информацията, свързана по-долу.
- asp.net ядро 2.2 brotli компресия не работи на IIS?
- Общ преглед на компресирането на IIS
- WebGL: Примерен код за конфигуриране на сървъра
- WebGL - Разполагане на компресирани компилации
Съобщение за грешка
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)