Running Unity WebGL s ASP.NET jedrom

Stran posodobljena :
Datum ustvarjanja strani :

Okolje za preverjanje

Windows
  • Windows 11
Urejevalnik Unity
  • 2020.3.25F1
Visual Studio
  • Visual Studio 2022
ASP.NET jedro
  • ASP.NET Core 6.0
Internetne informacijske storitve (IIS)
  • Storitve IIS 10.0

Sprva

Naučite se zagnati izhod igre kot WebGL v aplikaciji Unity v spletnem strežniku, ki se izvaja ASP.NET Core. Za programe iger uporabite tiste, ki so na voljo v spodnjih korakih z nasveti. Primer igre uporablja 2D Platformer Microgame, ki ga lahko ustvarite iz središča Unity.

Razložil bom, kako nastaviti "Nestisnjen WebGL", "WebGL stisnjen z Gzipom" in "WebGL stisnjen z Brotlijem" za zagon iger WebGL. Postopek je enak za vse.

Uporabljamo Visual Studio 2022, ASP.NET Core 6.0, vendar bodo starejše različice verjetno delovale. Vendar pa je struktura začetne kode za vsako različico drugačna, zato prosimo, da razlike razumete sami.

Ustvarjanje osrednjega projekta ASP.NET

Zaženite "Visual Studio 2022" iz začetnega menija.

Izberite Ustvari nov projekt.

Tokrat za vzorec izberite »ASP.NET Core Web App«. Če se izvajate ASP.NET jedru, lahko zaženete druge predloge, vendar boste morali vsaki predlogi slediti, kako jo ustvariti.

Poljubno nastavite ime in lokacijo projekta.

Dodatne informacije pustite takšne, kot so.

Projekt je nastal.

Zaženite nestisnjen WebGL

Pripravite program WebGL, ustvarjen brez stiskanja.

Prepričajte se, da igra deluje hitro

ASP.NET Poskusite zagnati igro WebGL z manj nastavitvami, ne da bi sledili osnovnemu bontonu.

V ASP.NET jedru ne morete dostopati do nekaterih datotek WebGL, ki jih oddaja Unity v privzetem stanju. Poskrbite, da bo to dostopno.

Program.cs

Odprite projekt Program.cs . Velja za starejše različice Startup.cs ASP.NET Core .

Dodajte imenski prostor na vrh kode in v kodi app.UseStaticFiles(); zamenjajte naslednje:

// ここから追加
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, tako da se lahko ob dostopu do .wasm datoteke vrne odjemalcu z določeno Content-Type .

Uvajanje WebGL

V projekt wwwroot vstavite te datotečne mape iz Unity .

  • indeks.html
  • Graditi
  • Podatki predloge

Index.cshtmlindex.html Odprite povezavo, da boste lahko dostopali do nje.

<!-- 省略 -->

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

Zaženite program in se prepričajte, da igra deluje.

Zaženite program WebGL na strani Razor

Prejšnja igra je delovala na statični datoteki HTML, zato deluje na mestu, ki nima nič skupnega s ASP.NET jedrom. To ni zelo zaželeno za enotnost programa, zato bomo vedenje datoteke HTML premaknili na strani Razor.

Z desno tipko miške kliknite mapo Strani v projektu, da dodate nov element.

Izberite Stran z britvico - prazno. Ni določenega posebnega imena, vendar je dodano tukaj WebGL.cshtml .

Koda je prikazana.

index.html Oglejte si vsebino datoteke in vrata na WebGL.cshtml . link Obstaja nekaj čudnih točk, na primer, kako postaviti oznako, vendar jo bom pustil takšno, kot je zaradi preprostosti razlage.

@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 Dodajte povezavo do .

<!-- 省略 -->

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

Poskusite zagnati program. Vidite lahko, da sta glava in noga _Layout.cshtml prikazani na strani WebGL glede na .

Spreminjanje lokacije datotek WebGL

Datoteko WebGL sem postavil neposredno pod , vendar jo bo ta metoda prepisala, ko postavite dve ali več datotek WebGL wwwroot . Razložil bom, kako to postaviti v ločene mape in ga premakniti.

Najprej ustvarite novo mapo z imenom "webgl" in jo premaknite tja. Dve mapi, ki ju je treba premakniti, sta, Build. TemplateData index.html Prenesel sem ga že na strani Razor in ga lahko varno izbrišem.

Ker WebGL.cshtml smo poglobili hierarhijo map, bomo poglobili tudi pot, opisano v . Popravek je 3 vrstice.

Pred korekcijo

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

Po korekciji

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

Zaženite program in preverite, ali deluje pravilno.

Izvajanje WebGL, stisnjeno z Gzipom

Razširitev datoteke, stisnjene z Gzipom, je , in to je .gz datoteka, ki jo lahko obravnava ASP.NET jedro, Unity WebGL Content-Type in se obravnavajo drugače in zahtevajo pretvorbo.

Najprej ustvarite uvajanje datotek WebGL in stran.

Postavitev datoteke WebGL

wwwrootwebgl-gzip Ustvarite mapo v razdelku Gzip in kopirajte mapo , iz datoteke BuildTemplateData WebGL, ki ste jo ustvarili z Gzipom.

Ustvarjanje strani z britvico

Tokrat WebGLGzip.cshtml ustvarite datoteko po enakem postopku kot pri nestisnjenju.

Koda je naslednja glede na izhod v index.html enotnosti. Pot se ujema z mapo, ki ste jo prej ustvarili webgl-gzip za datoteke 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>
}

Spremeni, da omogočite krmarjenje do Index.cshtml te strani.

<!-- 省略 -->

<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 določanja.cs

app.UseStaticFiles Del, ki obdeluje metodo, spremenite na naslednji način.

Pred korekcijo

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

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

Po korekciji

// ここから追加
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 se datoteka Content-Type application/x-gzip vrne z . Kot je, Unity WebGL na odjemalcu ga ne more določiti, zato .gz ga ponovno napišem in vrnem glede Content-Type na razširitev datoteke, ki izključuje . Content-Encoding Postavil sem ga tudi zato, ker je gzip to potrebno.

Mimogrede, tudi Brottijevo kodo sem sestavil, tako da lahko to kodo uporabite tako, kot je v Brotlijevi korespondenci naslednjega elementa. Brotli nastavi tudi .br prepisovanje Content-Encoding br, da se ujema s Content-Type pripono datoteke brez . Vendar pa je datoteka privzeto nedostopna v ASP.NET jedru,.br zato provider.Mappings sem jo dodal z .br .

Po tem zaženite odpravljanje napak in preverite, ali igra deluje pravilno.

Če ste ga pravilno nastavili in se igra še vedno ne prikaže, poskusite počistiti predpomnilnik spletnega brskalnika, da izbrišete piškotke.

Zagon WebGL, stisnjen z Brotli

Postopek je skoraj enak kot Gzip, ki nadomešča del Gzip z Brotlijem. Vendar pa datoteke Brotli (.br) privzeto niso dostopne v ASP.NET jedru. Konfigurirati ga morate tako, da lahko dostopate do njega, če pa kodo uporabljate v času Gzipa, je podprta.

Najprej ustvarite uvajanje datotek WebGL in stran.

Postavitev datoteke WebGL

wwwrootwebgl-brotli V razdelku Ustvari mapo kopirajte mapo , iz BuildTemplateData datoteke WebGL, ki ste jo ustvarili z Brotlijem.

Ustvarjanje strani z britvico

Ustvarite datoteko z WebGLBrotli.cshtml enakimi koraki kot za Gzip.

Koda je naslednja glede na izhod v index.html enotnosti. Pot se ujema z mapo, ki ste jo prej ustvarili webgl-brotli za datoteke 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>
}

Spremeni, da omogočite krmarjenje do Index.cshtml te strani.

<!-- 省略 -->

<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 določanja.cs

Če jo spremenite, ko je Gzip podprt, lahko uporabite isto kodo.

Ko ga popravite, zaženite odpravljanje napak in preverite, ali igra deluje.

Če ste ga pravilno nastavili in se igra še vedno ne prikaže, poskusite počistiti predpomnilnik spletnega brskalnika, da izbrišete piškotke.

Razumevanje simptomov dostopa do datotek Brotli v spletnem strežniku storitev IIS

Storitve IIS privzeto ne podpirajo storitve Brotli, zato je potrebna konfiguracija na strani storitev IIS. Zdi se, da ga je mogoče obravnavati z naprednimi nastavitvami, vendar tega v tem nasvetu ne bom razložil. Oglejte si spodnje informacije.

Sporočilo o napaki

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)