학습 기록하기/Unity

[Unity] 유니티에서 WebGL 템플릿을 직접 커스텀해보자: WebGL Custom Templete

nanalyee 2023. 11. 22. 10:26

Goal

 🥅 직접 WebGL Templete을 커스텀해보자

Problem

🚨 이전에 다른 개발자들이 제공하는 템플릿은 전혀 먹히지 않았다

대부분 UnityLoader 를 사용했는데 UnityLoader is not defined 에러가 발생하며 전혀 작동하지 않았다. 그래서 유니티포럼 검색 결과 유니티 2020 버전 이후로는 UnityLoader 관련 플러그인 등이 호환되지 않음을 알게 되었다!

WebGL build not working correctly. "UnityLoader is not defined".

 

WebGL build not working correctly. "UnityLoader is not defined".

hey, i have two issues with my unity when i try to build for WebGL. Unity ver- 2020.1.6f1 1. after build is finished when i open console - i see the...

forum.unity.com

그래서 나는 해당 포럼 글에서 default 템플릿을 받을 수 있었고, 해당 코드를 내 입맛에 맞게 최소한으로 수정해서 사용했다.

우선 나는 fullscreen의 기능만 있으면 됐기때문에 로고를 지우고, 코드를 이해할 겸 해상도를 조절해 보았다.

Cause & Solution

💡 default templete의 원본 코드는 다음과 같다.

<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Unity WebGL Player | {{{ PRODUCT_NAME }}}</title>
    <link rel="shortcut icon" href="TemplateData/favicon.ico">
    <link rel="stylesheet" href="TemplateData/style.css">
  </head>
  <body>
    <div id="unity-container" class="unity-desktop">
      <canvas id="unity-canvas" width={{{ WIDTH }}} height={{{ HEIGHT }}}></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-mobile-warning">
        WebGL builds are not supported on mobile devices.
      </div>
      <div id="unity-footer">
        <div id="unity-webgl-logo"></div>
        <div id="unity-fullscreen-button"></div>
        <div id="unity-build-title">{{{ PRODUCT_NAME }}}</div>
      </div>
    </div>
    <script>
      var buildUrl = "Build";
      var loaderUrl = buildUrl + "/{{{ LOADER_FILENAME }}}";
      var config = {
        dataUrl: buildUrl + "/{{{ DATA_FILENAME }}}",
        frameworkUrl: buildUrl + "/{{{ FRAMEWORK_FILENAME }}}",
        codeUrl: buildUrl + "/{{{ CODE_FILENAME }}}",
#if MEMORY_FILENAME
        memoryUrl: buildUrl + "/{{{ MEMORY_FILENAME }}}",
#endif
#if SYMBOLS_FILENAME
        symbolsUrl: buildUrl + "/{{{ SYMBOLS_FILENAME }}}",
#endif
        streamingAssetsUrl: "StreamingAssets",
        companyName: "{{{ COMPANY_NAME }}}",
        productName: "{{{ PRODUCT_NAME }}}",
        productVersion: "{{{ PRODUCT_VERSION }}}",
      };

      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 mobileWarning = document.querySelector("#unity-mobile-warning");

      // By default Unity keeps WebGL canvas render target size matched with
      // the DOM size of the canvas element (scaled by window.devicePixelRatio)
      // Set this to false if you want to decouple this synchronization from
      // happening inside the engine, and you would instead like to size up
      // the canvas DOM size and WebGL render target sizes yourself.
      // config.matchWebGLToCanvasSize = false;

      if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
        container.className = "unity-mobile";
        // Avoid draining fillrate performance on mobile devices,
        // and default/override low DPI mode on mobile browsers.
        config.devicePixelRatio = 1;
        mobileWarning.style.display = "block";
        setTimeout(() => {
          mobileWarning.style.display = "none";
        }, 5000);
      } else {
        canvas.style.width = "{{{ WIDTH }}}px";
        canvas.style.height = "{{{ HEIGHT }}}px";
      }
#if BACKGROUND_FILENAME
      canvas.style.background = "url('" + buildUrl + "/{{{ BACKGROUND_FILENAME.replace(/'/g, '%27') }}}') center / cover";
#endif
      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>
  </body>
</html>

나는 불필요한 로고와 제목을 지우고 풀스크린 버튼만 살려두었다.

<div id="unity-container" class="unity-desktop">
      <canvas id="unity-canvas"></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-mobile-warning">
        WebGL builds are not supported on mobile devices.
      </div>
      <div id="unity-footer">
        <div id="unity-fullscreen-button"></div>
        <!--
        <div id="unity-webgl-logo"></div>
        <div id="unity-build-title">{{{ PRODUCT_NAME }}}</div>
        -->
      </div>
    </div>

그리고 해상도를 조절하기 위해 여러가지를 만져봤는데, 원본에서 unity content가 들어갈 canvas의 width height 속성을 지워주고 javascript에서 수정하는게 바로 작동이 됐다.

else {
  //canvas.style.width = "{{{WIDTH}}}px";
  //canvas.style.height = "{{{HEIGHT}}}px";
  canvas.style.width = "calc(100vw - 20px)";
  canvas.style.height = "calc(100vh - 50px)";
}

풀스크린보다 조금 작게 사용하기 위해 calc 연산자를 섞어서 넣었는데, 그냥 “”안에 원하는 px 혹은 em 등의 사이즈를 넣으면 된다

비슷한 방법으로 나는 로딩창도 아예 없애버렸다. 로딩 이미지 같은 경우는 templatedata안에서 사진 파일을 교체해주면 될 것 같다. (default 템플릿은 유니티 포럼 링크 참고)

What I Felt

 💟 포럼에서 본 것처럼 갑작스럽게 바뀐 것 같던데.. 플러그인 제작자들이 업데이트하느라 꽤 고생한 것 같다. 나중에 시간이 되면 내 입맛에 맞게 템플릿을 잘 제작해두고 돌려 사용해보고 싶다.