Unity WebGL:n käyttäminen ASP.NET Coren kanssa
Varmennusympäristö
- Windows
-
- Windows 11
- Unity-editori
-
- 2020.3.25F1
- Visuaalinen studio
-
- Visuaalinen studio 2022
- ASP.NET ydin
-
- ASP.NET Core 6.0
- Internet Information Services (IIS)
-
- IIS 10.0
Alun perin
Lue, miten voit suorittaa pelitulosteen WebGL-muodossa Unity-muodossa ASP.NET Coren verkkopalvelimessa. Käytä peliohjelmissa alla olevien vinkkivaiheiden tulosteita. Peliesimerkissä käytetään 2D-tasohyppelymikropeliä, joka voidaan luoda Unity Hubista.
Selitän, kuinka "Pakkaamaton WebGL", "Gzipillä pakattu WebGL" ja "Brotlilla pakattu WebGL" määritetään WebGL-pelien suorittamiseen. Menettely on sama kaikille.
Käytämme Visual Studio 2022:ta ASP.NET Core 6.0:aa, mutta vanhemmat versiot toimivat todennäköisesti. Alkuperäisen koodin rakenne on kuitenkin erilainen jokaisessa versiossa, joten ymmärrä erot itse.
ASP.NET ydinprojektin luominen
Käynnistä "Visual Studio 2022" aloitusvalikosta.
Valitse Luo uusi projekti.
Valitse tällä kertaa näytteeksi "ASP.NET Core Web App". Jos käytät ASP.NET Corea, voit suorittaa muita malleja, mutta sinun on noudatettava kutakin mallia, miten se luodaan.
Aseta projektin nimi ja sijainti mielivaltaisesti.
Jätä lisätiedot ennalleen.
Projekti on luotu.
Suorita pakkaamaton WebGL
Valmistele WebGL-ohjelma, joka on luotu ilman pakkausta.
Varmista, että peli toimii nopeasti
ASP.NET Kokeile WebGL-peliä vähemmillä asetuksilla noudattamatta ydinetikettiä.
ASP.NET Coressa et voi käyttää joitakin Unityn lähettämiä WebGL-tiedostoja oletustilassa. Tee tästä helppokäyttöinen.
Ohjelma.cs
Avaa projektista. Program.cs
Koskee aiempia ASP.NET Core-versioita Startup.cs
.
Lisää nimiavaruus koodin yläosaan ja korvaa koodissa app.UseStaticFiles();
seuraava:
// ここから追加
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
, jotta kun tiedostoa käytetään, .wasm
se voidaan palauttaa asiakkaalle määritetyllä Content-Type
.
WebGL:n käyttöönotto
Sijoita seuraavat Unity-tiedostokansiot projektiisi wwwroot
.
- indeksi.html
- Rakentaa
- TemplateData
Index.cshtml
index.html
Avaa linkki, jotta voit käyttää sitä.
<!-- 省略 -->
<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>
Suorita ohjelma ja varmista, että peli toimii.
WebGL-ohjelman suorittaminen Razor-sivulla
Edellinen peli toimi staattisella HTML-tiedostolla, joten se toimii paikassa, jolla ei ole mitään tekemistä ASP.NET Coren kanssa. Se ei ole kovin toivottavaa ohjelman yhtenäisyyden kannalta, joten siirrämme HTML-tiedoston toiminnan Razor Pagesiin.
Klikkaa hiiren kakkospainikkeella projektin Pages-kansiota lisätäksesi uuden kohteen.
Valitse Partakoneen sivu - tyhjä. Erityistä nimeä ei ole määritetty, mutta se lisätään tähän WebGL.cshtml
.
Koodi tulee näkyviin.
index.html
Katso tiedoston ja portin sisällöstä . WebGL.cshtml
link
On joitain outoja kohtia, kuten tunnisteen sijoittaminen, mutta jätän sen sellaisenaan selityksen yksinkertaisuuden vuoksi.
@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
Lisää linkki kohteeseen .
<!-- 省略 -->
<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>
Yritä suorittaa ohjelma. Voit nähdä, että ylä- ja alatunniste _Layout.cshtml
näkyvät WebGL-sivulla .
WebGL-tiedostojen sijainnin muuttaminen
Laitoin WebGL-tiedoston suoraan kohtaan , mutta tämä menetelmä korvaa sen, kun sijoitat kaksi tai useampia WebGL-tiedostoja wwwroot
.
Selitän, kuinka laittaa tämä erillisiin kansioihin ja siirtää se.
Luo ensin uusi kansio nimeltä "webgl" ja siirrä se sinne. Kaksi siirrettävää kansiota Build
ovat , TemplateData
.
index.html
Olen jo siirtänyt sen Razor Pagesiin ja voin poistaa sen turvallisesti.
Koska WebGL.cshtml
olemme syventäneet kansiohierarkiaa, syvennämme myös . Korjaus on 3 riviä.
Ennen korjausta
<link rel="shortcut icon" href="TemplateData/favicon.ico">
<link rel="stylesheet" href="TemplateData/style.css">
var buildUrl = "Build";
Korjauksen jälkeen
<link rel="shortcut icon" href="webgl/TemplateData/favicon.ico">
<link rel="stylesheet" href="webgl/TemplateData/style.css">
var buildUrl = "webgl/Build";
Suorita ohjelma nähdäksesi, toimiiko se oikein.
Gzipillä pakatun WebGL: n suorittaminen
Gzipin pakkaaman tiedoston laajennus on , ja se on .gz
tiedosto, jota ASP.NET Core voi käsitellä,
Unity WebGL Content-Type
ja niitä käsitellään eri tavalla ja vaativat muuntamista.
Luo ensin WebGL-tiedoston käyttöönotto ja sivu.
WebGL-tiedostojen sijoittelu
wwwroot
webgl-gzip
Luo kansio Gzip-kansioon ja kopioi -kansio Gzipillä luomastasi WebGL-tiedostostaBuild
TemplateData
.
Luo partaveitsisivu
Luo tällä kertaa WebGLGzip.cshtml
tiedosto samalla tavalla kuin pakkaamattomana.
Koodi on seuraava viitaten Output in Unity -toimintoon index.html
.
Polku vastaa kansiota, jonka loit webgl-gzip
aiemmin WebGL-tiedostoille.
@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>
}
Muokkaa salliaksesi siirtymisen Index.cshtml
tälle sivulle.
<!-- 省略 -->
<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>
Ohjelman korjaaminen.cs
app.UseStaticFiles
Muokkaa menetelmää käsittelevää osaa seuraavasti.
Ennen korjausta
// ここから追加
var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".data"] = "application/octet-stream";
provider.Mappings[".wasm"] = "application/wasm";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = provider,
});
// ここまで追加
Korjauksen jälkeen
// ここから追加
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 Coressa .gz
tiedosto Content-Type
application/x-gzip
palauttaa .
Kuten se on, asiakkaan Unity WebGL ei voi määrittää sitä, joten .gz
kirjoitan ja palautan sen tiedoston laajennuksen mukaan Content-Type
, joka sulkee pois .
Content-Encoding
Asetan sen myös siksi, että se gzip
on välttämätöntä.
Muuten, laitoin myös Brotli-koodin yhteen, joten voit käyttää tätä koodia sellaisena kuin se on seuraavan kohteen Brotli-kirjeenvaihdossa.
Brotli asettaa myös .br
uudelleenkirjoituksen Content-Encoding
br
vastaamaan Content-Type
tiedoston laajennusta ilman .
Tiedosto ei kuitenkaan ole oletusarvoisesti käytettävissä ASP.NET Coressa,.br
joten provider.Mappings
lisäsin sen .br
.
Tämän jälkeen suorita virheenkorjaus ja tarkista, toimiiko peli oikein.
Jos olet määrittänyt sen oikein, mutta peli ei vieläkään näy, yritä tyhjentää selaimesi välimuisti evästeiden tyhjentämiseksi.
Brotlilla pakatun WebGL:n suorittaminen
Menettely on melkein sama kuin Gzip, korvaamalla Gzip-osa Brotlilla. Brotli (.br) -tiedostot eivät kuitenkaan ole oletusarvoisesti käytettävissä ASP.NET Coressa. Sinun on määritettävä se niin, että voit käyttää sitä, mutta jos käytät koodia Gzipin aikaan, sitä tuetaan.
Luo ensin WebGL-tiedoston käyttöönotto ja sivu.
WebGL-tiedostojen sijoittelu
wwwroot
webgl-brotli
Kopioi Luo kansio -kohdassa , -kansio Brotlilla luomastasi WebGL-tiedostostaBuild
TemplateData
.
Luo partaveitsisivu
Luo tiedosto WebGLBrotli.cshtml
samoilla vaiheilla kuin Gzipille.
Koodi on seuraava viitaten Output in Unity -toimintoon index.html
.
Polku vastaa kansiota, jonka loit webgl-brotli
aiemmin WebGL-tiedostoille.
@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>
}
Muokkaa salliaksesi siirtymisen Index.cshtml
tälle sivulle.
<!-- 省略 -->
<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>
Ohjelman korjaaminen.cs
Jos muokkaat sitä, kun Gzipiä tuetaan, voit käyttää samaa koodia.
Kun olet korjannut sen, suorita virheenkorjaus ja tarkista, toimiiko peli.
Jos olet määrittänyt sen oikein, mutta peli ei vieläkään näy, yritä tyhjentää selaimesi välimuisti evästeiden tyhjentämiseksi.
Brotli-tiedostojen käyttämisen oireita IIS-verkkopalvelimessa
IIS ei oletusarvoisesti tue Brotlia, joten IIS-puolen määritys vaaditaan. Näyttää siltä, että sitä voidaan käsitellä tekemällä lisäasetuksia, mutta en selitä sitä tässä vinkissä. Katso alla linkitetyt tiedot.
- asp.net Core 2.2 brotli -pakkaus ei toimi IIS: ssä?
- IIS-pakkauksen yleiskatsaus
- WebGL: Palvelimen määrityskoodin esimerkki
- WebGL - pakattujen koontiversioiden käyttöönotto
virheviesti
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)