Spuštění Unity WebGL s ASP.NET Core

Stránky aktualizovány :
Datum vytvoření stránky :

Ověřovací prostředí

Windows
  • Systém Windows 11
Editor jednoty
  • 2020.3.25f1
Visual Studio
  • Visual Studio 2022
ASP.NET jádro
  • ASP.NET Core 6.0
Internetová informační služba (IIS)
  • Služba IIS 10.0

Nejprve

Naučte se, jak spustit herní výstup jako WebGL v Unity na webovém serveru se systémem ASP.NET Core. U herních programů použijte výstupy v níže uvedených tipech. Příklad hry používá 2D plošinovkovou mikrohru, kterou lze vytvořit z Unity Hubu.

Vysvětlím, jak nastavit "Uncompressed WebGL", "WebGL compressed with Gzip" a "WebGL compressed with Brotli" pro spouštění WebGL her. Postup je stejný pro všechny z nich.

Používáme Visual Studio 2022, ASP.NET Core 6,0, ale starší verze budou pravděpodobně fungovat. Struktura počátečního kódu je však pro každou verzi odlišná, proto prosím pochopte rozdíly sami.

Vytvoření základního projektu ASP.NET

Spusťte "Visual Studio 2022" z nabídky Start.

Vyberte vytvořit nový projekt.

Tentokrát vyberte jako ukázku "ASP.NET Core Web App". Pokud používáte ASP.NET Core, můžete spouštět jiné šablony, ale budete muset postupovat podle jednotlivých šablon, jak je sestavit.

Nastavte název a umístění projektu libovolně.

Další informace ponechte tak, jak jsou.

Projekt byl vytvořen.

Spuštění nekomprimovaného WebGL

Připravte program WebGL vytvořený bez komprese.

Ujistěte se, že hra funguje rychle

ASP.NET Zkuste spustit hru WebGL s menším počtem nastavení bez dodržení základní etikety.

V ASP.NET Core nemáte přístup k některým souborům WebGL vygenerovaným Unity ve výchozím stavu. Učiňte to přístupným.

Program.cs

Otevřete z projektu Program.cs . Platí pro starší verze Startup.cs ASP.NET Core.

Přidejte obor názvů do horní části kódu a nahraďte následující v kódu 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, takže při přístupu .wasm k souboru jej lze vrátit klientovi se zadaným Content-Type souborem .

Nasazení WebGL

Do projektu wwwroot umístěte následující složky souborů z Unity.

  • index.html
  • Vybudovat
  • TemplateData

Index.cshtmlindex.html Otevřete odkaz, abyste k němu měli přístup.

<!-- 省略 -->

<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>

Spusťte program a ujistěte se, že hra funguje.

Spuštění programu WebGL na stránce Razor

Předchozí hra běžela na statickém souboru HTML, takže běží na místě, které nemá nic společného s ASP.NET Core. Není to příliš žádoucí pro jednotnost programu, takže přesuneme chování souboru HTML na Razor Pages.

Klikněte pravým tlačítkem na složku Stránky v projektu a přidejte novou položku.

Vyberte Razor Page – empty. Není zadán žádný konkrétní název, ale je zde WebGL.cshtml přidán.

Zobrazí se kód.

index.html Viz obsah souboru a port do WebGL.cshtml . link Existují některé podivné body, jako například jak umístit značku, ale nechám to tak, jak to je, kvůli jednoduchosti vysvětlení.

@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.cshtmlWebGL Přidejte odkaz na soubor .

<!-- 省略 -->

<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>

Zkuste spustit program. Můžete vidět, že záhlaví a zápatí _Layout.cshtml jsou zobrazeny na stránce WebGL podle .

Změna umístění souborů WebGL

Soubor WebGL jsem umístil přímo pod , ale tato metoda jej přepíše, když umístíte dva nebo více souborů WebGL wwwroot . Vysvětlím, jak to dát do samostatných složek a přesunout to.

Nejprve vytvořte novou složku s názvem "webgl" a přesuňte ji tam. Dvě složky, které mají být přesunuty, jsou , BuildTemplateData . index.html Už jsem ji přenesl na Razor Pages a mohu ji bezpečně odstranit.

Vzhledem k tomu, že WebGL.cshtml jsme prohloubili hierarchii složek, prohloubíme také cestu popsanou v . Korekce je 3 řádky.

Před opravou

<link rel="shortcut icon" href="TemplateData/favicon.ico">
<link rel="stylesheet" href="TemplateData/style.css">
    var buildUrl = "Build";

Po opravě

<link rel="shortcut icon" href="webgl/TemplateData/favicon.ico">
<link rel="stylesheet" href="webgl/TemplateData/style.css">
    var buildUrl = "webgl/Build";

Spusťte program a zjistěte, zda funguje správně.

Spuštění WebGL komprimovaného pomocí Gzip

Přípona souboru komprimovaného Gzip je .gz , a je to soubor, který může zpracovat ASP.NET Core, Unity WebGL Content-Type a jsou zpracovány odlišně a vyžadují konverzi.

Nejprve vytvořte nasazení souboru WebGL a stránku.

Umístění souboru WebGL

wwwrootwebgl-gzip Vytvořte složku pod Gzip a zkopírujte složku , ze souboru BuildTemplateData WebGL, který jste vytvořili pomocí programu Gzip.

Vytvoření stránky Razor

Tentokrát WebGLGzip.cshtml vytvořte soubor stejným postupem jako při dekomprimaci.

Kód je následující s odkazem na výstup v index.html jednotce. Cesta odpovídá složce, kterou jste vytvořili webgl-gzip dříve pro soubory 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>
}

Upravit tak, aby umožňoval navigaci na Index.cshtml tuto stránku.

<!-- 省略 -->

<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>

Fixační program.cs

app.UseStaticFiles Upravte část, která zpracovává metodu následujícím způsobem.

Před opravou

// ここから追加
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".data"] = "application/octet-stream";
provider.Mappings[".wasm"] = "application/wasm";

app.UseStaticFiles(new StaticFileOptions()
{
  ContentTypeProvider = provider,
});
// ここまで追加

Po opravě

// ここから追加
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");
      }
    }
  },
});
// ここまで追加

V ASP.NET Core .gz vrátí soubor Content-Type application/x-gzip s . Jak to je, Unity WebGL na klientovi to nemůže určit, takže .gz to přepíšu a vracím podle Content-Type přípony souboru, který vylučuje . Content-Encoding Také jsem to nastavil, protože je to gzip nutné.

Mimochodem, také jsem dal dohromady kód Brocti, takže tento kód můžete použít tak, jak je v korespondenci Brotli další položky. Brotli také .br nastaví přepis Content-Encoding br tak, aby odpovídal Content-Type příponě souboru bez . Soubor je však ve výchozím nastavení v ASP.NET Core nepřístupný,.br takže provider.Mappings jsem ho přidal pomocí .br .

Poté spusťte ladění a zkontrolujte, zda hra funguje správně.

Pokud jste ji nastavili správně a hra se stále nezobrazuje, zkuste vymazat mezipaměť webového prohlížeče a vymazat soubory cookie.

Spuštění WebGL komprimovaného pomocí Brotli

Postup je téměř stejný jako Gzip, nahrazení části Gzip Brotli. Soubory Brotli (.br) však nejsou ve výchozím nastavení v ASP.NET Core přístupné. Musíte jej nakonfigurovat tak, abyste k němu měli přístup, ale pokud používáte kód v době Gzip, je podporován.

Nejprve vytvořte nasazení souboru WebGL a stránku.

Umístění souboru WebGL

wwwrootwebgl-brotli V části Vytvořit složku zkopírujte složku , ze souboru WebGL, který BuildTemplateData jste vytvořili pomocí Brotli.

Vytvoření stránky Razor

Vytvořte soubor stejným WebGLBrotli.cshtml postupem jako pro Gzip.

Kód je následující s odkazem na výstup v index.html jednotce. Cesta odpovídá složce, kterou jste vytvořili webgl-brotli dříve pro soubory 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>
}

Upravit tak, aby umožňoval navigaci na Index.cshtml tuto stránku.

<!-- 省略 -->

<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>

Fixační program.cs

Pokud jej upravíte, když je podporován Gzip, můžete použít stejný kód.

Po opravě spusťte ladění a zkontrolujte, zda hra funguje.

Pokud jste ji nastavili správně a hra se stále nezobrazuje, zkuste vymazat mezipaměť webového prohlížeče a vymazat soubory cookie.

Vysvětlení příznaků přístupu k souborům Brotli na webovém serveru služby IIS

Brotli není ve výchozím nastavení službou IIS podporován, takže je vyžadována konfigurace na straně služby IIS. Zdá se, že to lze zvládnout provedením pokročilých nastavení, ale v tomto tipu to nevysvětlím. Přečtěte si níže uvedené informace.

zpráva o chybě

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)