Uruchamianie Unity WebGL z ASP.NET Core

Strona zaktualizowana :
Data utworzenia strony :

Ś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.cshtmlindex.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.cshtmlWebGL 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 Buildprzeniesienia 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

wwwrootwebgl-gzip Utwórz folder w obszarze Gzip i skopiuj go z pliku WebGL utworzonego za pomocą programu BuildTemplateData 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

wwwrootwebgl-brotli W obszarze Utwórz folder skopiuj folder , z BuildTemplateData 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.

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)