Esecuzione di Unity WebGL con ASP.NET Core
Ambiente di verifica
- Finestre
-
- Windows 11
- Unity Editor
-
- 2020.3.25F1
- Visual Studio
-
- Visual Studio 2022
- ASP.NET Nucleo
-
- ASP.NET Core 6,0
- Internet Information Services (IIS)
-
- IIS 10.0
Dapprima
Scopri come eseguire l'output di un gioco come WebGL in Unity su un server Web che esegue ASP.NET Core. Per i programmi di gioco, utilizzare l'output di quelli nei passaggi di suggerimenti riportati di seguito. L'esempio di gioco utilizza il microgioco platform 2D, che può essere creato da Unity Hub.
Spiegherò come impostare "WebGL non compresso", "WebGL compresso con Gzip" e "WebGL compresso con Brotli" per eseguire giochi WebGL. La procedura è la stessa per tutti.
Stiamo usando Visual Studio 2022, ASP.NET Core 6.0, ma le versioni precedenti probabilmente funzioneranno. Tuttavia, la struttura del codice iniziale è diversa per ogni versione, quindi si prega di comprendere le differenze da soli.
Creazione di un progetto ASP.NET Core
Avvia "Visual Studio 2022" dal menu Start.
Seleziona Crea nuovo progetto.
Questa volta, selezionare "ASP.NET Core Web App" come esempio. Se stai eseguendo ASP.NET Core, puoi eseguire altri modelli, ma dovrai seguire ogni modello su come compilarlo.
Impostare il nome e la posizione del progetto in modo arbitrario.
Lasciare le informazioni aggiuntive così come sono.
Il progetto è stato creato.
Eseguire WebGL non compresso
Preparare un programma WebGL creato senza compressione.
Assicurati che il gioco funzioni rapidamente
ASP.NET Prova a eseguire un gioco WebGL con meno impostazioni senza seguire l'etichetta di base.
In ASP.NET Core, non è possibile accedere ad alcuni file WebGL emessi da Unity nello stato predefinito. Rendilo accessibile.
Programma.cs
Apri dal tuo Program.cs
progetto. Si applica alle versioni Startup.cs
precedenti di ASP.NET Core.
Aggiungere uno spazio dei nomi all'inizio del codice e sostituire quanto segue nel codice 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
, in modo che quando si accede a un file, .wasm
questo possa essere restituito al client con il file .Content-Type
Distribuzione WebGL
Inserire le seguenti cartelle di file da Unity nel progetto wwwroot
.
- indice.html
- Costruire
- TemplateData
Index.cshtml
index.html
Apri il link in modo da potervi accedere.
<!-- 省略 -->
<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>
Esegui il programma e assicurati che il gioco funzioni.
Eseguire un programma WebGL su una pagina Razor
Il gioco precedente girava su un file HTML statico, quindi viene eseguito in un luogo che non ha nulla a che fare con ASP.NET Core. Non è molto desiderabile per l'uniformità del programma, quindi sposteremo il comportamento del file HTML in Razor Pages.
Fai clic con il pulsante destro del mouse sulla cartella Pages del progetto per aggiungere un nuovo elemento.
Seleziona Pagina rasoio - Vuota. Non c'è un nome particolare specificato, ma è aggiunto qui WebGL.cshtml
.
Viene visualizzato il codice.
index.html
Fare riferimento al contenuto del file e alla porta a WebGL.cshtml
.
link
Ci sono alcuni punti strani, come come posizionare il tag, ma lo lascerò così com'è per semplicità di spiegazione.
@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
Aggiungere un collegamento a .
<!-- 省略 -->
<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>
Prova a eseguire il programma. Puoi vedere che l'intestazione e il piè di pagina vengono visualizzati nella pagina _Layout.cshtml
WebGL in base a .
Modificare la posizione dei file WebGL
Ho inserito il file WebGL direttamente sotto , ma questo metodo lo sovrascriverà quando si inseriscono due o più file WebGL wwwroot
.
Spiegherò come metterlo in cartelle separate e spostarlo.
Prima di tutto, crea una nuova cartella chiamata "webgl" e spostala lì. Le due cartelle da Build
spostare sono , TemplateData
.
index.html
L'ho già portato su Razor Pages e posso tranquillamente eliminarlo.
Poiché WebGL.cshtml
abbiamo approfondito la gerarchia delle cartelle, approfondiremo anche il percorso descritto in . La correzione è di 3 righe.
Prima della correzione
<link rel="shortcut icon" href="TemplateData/favicon.ico">
<link rel="stylesheet" href="TemplateData/style.css">
var buildUrl = "Build";
Dopo la correzione
<link rel="shortcut icon" href="webgl/TemplateData/favicon.ico">
<link rel="stylesheet" href="webgl/TemplateData/style.css">
var buildUrl = "webgl/Build";
Eseguire il programma per vedere se funziona correttamente.
Esecuzione di WebGL compresso con Gzip
L'estensione del file compresso da Gzip è , ed è .gz
un file che può essere gestito da ASP.NET Core,
Unity WebGL Content-Type
e sono gestiti in modo diverso e richiedono la conversione.
Innanzitutto, creare una pagina e una distribuzione di file WebGL.
Posizionamento di file WebGL
wwwroot
webgl-gzip
Crea una cartella in Gzip e copia la cartella , dal file Build
TemplateData
WebGL creato con Gzip.
Creare una pagina Razor
Questa volta WebGLGzip.cshtml
creare il file utilizzando la stessa procedura di quando non compresso.
Il codice è il seguente con riferimento a Output in index.html
Unity.
Il percorso corrisponde alla cartella creata webgl-gzip
in precedenza per i file 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 per consentire la navigazione verso Index.cshtml
questa pagina.
<!-- 省略 -->
<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>
Programma di riparazione.cs
app.UseStaticFiles
Modificare la parte che sta elaborando il metodo come indicato di seguito.
Prima della correzione
// ここから追加
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".data"] = "application/octet-stream";
provider.Mappings[".wasm"] = "application/wasm";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = provider,
});
// ここまで追加
Dopo la correzione
// ここから追加
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");
}
}
},
});
// ここまで追加
In ASP.NET Core .gz
, il file Content-Type
application/x-gzip
restituisce con .
Così com'è, Unity WebGL sul client non può determinarlo, quindi .gz
lo riscrivo e lo restituisco in base all'estensione Content-Type
del file che esclude .
Content-Encoding
L'ho impostato anche perché gzip
è necessario.
A proposito, ho anche messo insieme il codice Brotli, in modo da poter utilizzare questo codice così com'è nella corrispondenza Brotli dell'elemento successivo.
Brotli imposta anche .br
la riscrittura Content-Encoding
br
in modo che corrisponda Content-Type
all'estensione del file senza .
Tuttavia, il file è inaccessibile per impostazione predefinita in ASP.NET Core,.br
quindi provider.Mappings
l'ho aggiunto con .br
.
Successivamente, esegui il debug e controlla se il gioco funziona correttamente.
Se l'hai impostato correttamente e il gioco continua a non essere visualizzato, prova a svuotare la cache del browser web per cancellare i cookie.
Esecuzione di WebGL compresso con Brotli
La procedura è quasi la stessa di Gzip, sostituendo la parte Gzip con Brotli. Tuttavia, i file Brotli (.br) non sono accessibili per impostazione predefinita in ASP.NET Core. È necessario configurarlo in modo da potervi accedere, ma se si utilizza il codice al momento di Gzip, è supportato.
Innanzitutto, creare una pagina e una distribuzione di file WebGL.
Posizionamento di file WebGL
wwwroot
webgl-brotli
In Crea una cartella copiare la cartella , dal Build
TemplateData
file WebGL creato con Brotli.
Creare una pagina Razor
Crea il file seguendo WebGLBrotli.cshtml
gli stessi passaggi di Gzip.
Il codice è il seguente con riferimento a Output in index.html
Unity.
Il percorso corrisponde alla cartella creata webgl-brotli
in precedenza per i file 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 per consentire la navigazione verso Index.cshtml
questa pagina.
<!-- 省略 -->
<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>
Programma di riparazione.cs
Se lo modifichi quando Gzip è supportato, puoi usare lo stesso codice.
Dopo averlo risolto, esegui il debug e controlla se il gioco funziona.
Se l'hai impostato correttamente e il gioco continua a non essere visualizzato, prova a svuotare la cache del browser web per cancellare i cookie.
Informazioni sui sintomi dell'accesso ai file Brotli su un server Web IIS
Brotli non è supportato da IIS per impostazione predefinita, quindi è necessaria la configurazione sul lato IIS. Sembra che possa essere gestito effettuando impostazioni avanzate, ma non lo spiegherò in questo suggerimento. Si prega di fare riferimento alle informazioni collegate di seguito.
- asp.net compressione brotli core 2.2 non funziona su IIS?
- Panoramica della compressione IIS
- WebGL: esempio di codice di configurazione del server
- WebGL - Distribuzione di build compresse
Messaggio di errore
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)