技術共有

Unity WebGL はフロントエンド Web ページを埋め込んで通信します

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1 はじめに

最近、プロジェクトに取り組んでいるときに、Web ページに UnityWebGL を埋め込む必要が生じました。Web ページ上のボタンをクリックしたときに UnityWebGL が応答する必要があります。新しいプロジェクト部分を直接スキップします

2. 最終的な効果

webglResult.gif

3. 基本設定

  • エクスポート プラットフォームを WebGL に設定する
    貼り付けた画像 20240527102413
  • プレーヤー設定 -> 公開設定を確認してください Data Caching そしてDecompression Fallback 以下のリンクが公式の説明です。
    Data Caching 簡単に言うと、データはローカルにキャッシュされ、次回開くときはダウンロードせずに直接ゲームに入ることができます。
    Decompression Fallback gz ファイルを解析できない場合、Web サーバー構成エラーなどが発生する場合は、このオプションをチェックする必要があります。
    Unity - マニュアル: WebGL プレーヤーの設定 (unity3d.com)
    貼り付けた画像 20240527102930

4. コードの作成とエクスポート

  • シーンは次のように設定されています(必要に応じてシーンを作成できます)
    貼り付けた画像 20240527110105
  • コード部分(作成したCubeにコードを実装)

注: メソッドはパブリックである必要があります。そうでない場合はアクセスできません。

using System;  
using System.Text;  
using UnityEngine;  
using UnityEngine.UI;  
  
public class CubeRotate : MonoBehaviour  
{  
    public Text tx;  
  
    void Update()  
    {        
	    transform.Rotate(Vector3.up * Time.deltaTime * 30, Space.World);  
    }  
    public void SetTextInfo(string info)  
    {        byte[] bytes = Convert.FromBase64String(info);  
        var decodedMessage = Encoding.UTF8.GetString(bytes);  
        Debug.Log($"收到消息:{info}----{decodedMessage}");  
        tx.text = decodedMessage;  
    }  
    public void AddScale()  
    {        
	    transform.localScale += Vector3.one * 0.1f;  
    }  
    public void SubtractScale()  
    {        
	    transform.localScale -= Vector3.one * 0.1f;  
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • WebGL をエクスポートします (エクスポートが完了するまで待ちます)
    貼り付けた画像 20240527110452

パッケージ化されたファイルをローカルで参照する場合は、ファイルをダウンロードする必要があります。 Firefox浏览器 、ダウンロードには特定の構成パラメータが必要です。Firefox で webgl を開く_Firefox で webgl を開く-CSDN ブログ

5. サンプル Web ページ

Web ページの書き方を知らない友人もいることを考慮して、著者は誰でもテストできる簡単な Web ページ テンプレートを提供します。

使用手順: 新しいテキスト ファイルを作成し、次のコードをそこに貼り付けて保存し、ファイルのサフィックスを次のように変更します。.html
貼り付けた画像 20240527114133

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Simple Web Page</title>
    <style>
      body {
        margin: 0;
        padding: 0;
        font-family: Arial, sans-serif;
      }
      .header {
        background-color: #333;
        color: white;
        padding: 10px;
        text-align: center;
      }
      .nav {
        background-color: #ddd;
        padding: 10px;
        text-align: center;
      }
      .nav-button {
        background-color: #ddd;
        border: none;
        color: #333;
        padding: 10px 15px;
        text-align: center;
        text-decoration: none;
        display: inline-block;
        font-size: 16px;
        margin: 4px 2px;
        cursor: pointer;
        border-radius: 4px; /* 圆角边框 */
      }
      .nav-button:hover {
        background-color: #ccc;
      }
      .nav a {
        color: #333;
        text-decoration: none;
        margin-right: 10px;
      }
      .container {
        display: flex;
        justify-content: space-between;
        padding: 20px;
      }
      .sidebar,
      .main {
        padding: 20px;
        height: 550px;
        overflow: hidden;
      }
      .sidebar {
        background-color: #f0f0f0;
        flex: 0 0 380px; /* Fixed width for sidebar */
      }
      .main {
        background-color: #e0e0e0;
        flex: 0 0 960px; /* Fixed width for main content */
      }
      .sidebar-left {
        margin-right: 20px; /* Adjust the margin for the left sidebar */
      }
      .sidebar-right {
        margin-left: 20px; /* Adjust the margin for the right sidebar */
      }
      .footer {
        background-color: #333;
        color: white;
        text-align: center;
        padding: 10px;
        position: fixed;
        bottom: 0;
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div class="header">
      <h1>My Simple Web Page</h1>
    </div>

    <div class="nav">
      <button id="enlargeButton" class="nav-button">放大</button>
      <button id="shrinkButton" class="nav-button">缩小</button>
      <button id="infoButton" class="nav-button">设置信息</button>
    </div>

    <div class="container">
      <div class="sidebar sidebar-left">
        <h2>Left Sidebar</h2>
        <p>
          This is the left sidebar area. It typically contains additional
          information or links.
        </p>
      </div>
      <div class="main">
        WebGL网页
      </div>
      <div class="sidebar sidebar-right">
        <h2>Right Sidebar</h2>
        <p>
          This is the right sidebar area. It typically contains additional
          information or links.
        </p>
      </div>
    </div>

    <div class="footer">
      <p>Footer - Copyright &copy; 2024</p>
    </div>
  </body>

  <script>
    // JS 代码
  </script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120

6. WebGLを埋め込む

  • 以下に示すように、フォルダーを作成し、パッケージ化された WebGL と Web ページを同じフォルダーに置きます (この手順は主に管理を容易にするためのものであり、これを行う必要はありません)
    貼り付けた画像 20240527114742
  • IDE を使用して Web ページを開き、以下のコード内の赤いボックスでマークされた場所を見つけます。
    貼り付けた画像 20240527114359
  • div タグのコンテンツを次のコードに置き換えます。WebGL プロジェクトがサーバーにデプロイされている場合は、iframe タグのコンテンツを次のコードに置き換えることができます。srcリンクをサーバーアドレスに変更するだけです。 (iframeについて詳しくはこちらをご覧ください)HTML Iframe (w3school.com.cn)) 保存して使用しますFirefox浏览器Web ページを開くと、サーバー上にデプロイされたプロジェクトを WebGL をサポートする任意のブラウザで開くことができます。
<iframe
          id="webgl"
          style="
            position: relative;
            width: 100%;
            height: 100%;
            border: medium none;
          "
          src="../UnWeb/webgl/index.html"
        ></iframe>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

貼り付けた画像 20240527115228
貼り付けた画像 20240527115718

実行結果

7. Web ページが Unity メソッドを呼び出す

  • 以下のコードの赤いボックスでマークされた場所を見つけます。
    貼り付けた画像 20240527121614
  • scriptタグ内の内容を以下のコードに置き換えます(コードは比較的シンプルでコメントも付いているので、説明は省略します)

知らせ:methodName Unity のメソッド名と一致している必要があります。そうでない場合、メソッドは見つかりません。

    // 获取DOM中id为"webgl"的iframe元素
    var unWebGL = document.getElementById("webgl");
    // 获取放大按钮
    var enlargeButton = document.getElementById("enlargeButton");
    // 获取缩小按钮
    var shrinkButton = document.getElementById("shrinkButton");
    // 获取信息按钮
    var infoButton = document.getElementById("infoButton");

    /**
     * Action函数用于向iframe内的WebGL应用发送指令。
     * @param {string} methodName - 要调用的方法名
     * @param {string} message - 要传递的消息(可选)
     */
    function Action(methodName, message) {
      // 获取嵌套的iframe元素
      var iframeB = document.getElementById("webgl");
      // 调用iframe内容窗口的ReceiveJSMethod方法,传递方法名和消息
      iframeB.contentWindow.ReceiveJSMethod(methodName, message);
    }

    // 为放大按钮添加点击事件监听器
    enlargeButton.addEventListener("click", function () {
      // 当按钮被点击时,调用Action函数,通知WebGL应用增大缩放
      Action("AddScale");
      // 可以在这里执行其他操作
    });

    // 为缩小按钮添加点击事件监听器
    shrinkButton.addEventListener("click", function () {
      // 当按钮被点击时,调用Action函数,通知WebGL应用减小缩放
      Action("SubtractScale");
    });

    // 为信息按钮添加点击事件监听器
    infoButton.addEventListener("click", function () {
      // 当按钮被点击时,调用Action函数,通知WebGL应用显示信息
      Action("SetTextInfo", "这是一条测试消息");
    });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

貼り付けた画像 20240527122058

  • 上記の手順を完了したら、IDE を使用して WebGL Web ページ (下の図のindex.html ファイル) を開きます。
    貼り付けた画像 20240527142351
  • script タグを見つけて、このタグの下でローダーを初期化するコードを見つけます。そして、赤枠内のコードを追加します。
    貼り付けた画像 20240527143058
var unityIns = null;
      script.src = loaderUrl;
      script.onload = () => {
        createUnityInstance(canvas, config, (progress) => {
          progressBarFull.style.width = 100 * progress + "%";
        })
          .then((unityInstance) => {
            unityIns = unityInstance;
            loadingBar.style.display = "none";
            fullscreenButton.onclick = () => {
              unityInstance.SetFullscreen(1);
            };
          })
          .catch((message) => {
            alert(message);
          });
      };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • Unity にメッセージを送信するコードを作成します。コード内で使用される内容を簡単に説明します。SendMessageメソッド これにより、JavaScript コードから Unity シーン内のゲーム オブジェクトの特定のメソッドを呼び出すことができます。

知らせ:SendMessage このメソッドには 3 つのパラメータがあります。
ターゲット オブジェクト名: これは、シーン内のゲーム オブジェクトの名前であり、このオブジェクト上で呼び出すメソッドが定義されます。
メソッド名: これは呼び出したいメソッドの名前です。ターゲット オブジェクトのスクリプト内のパブリック メソッドである必要があります。
パラメータ: これらはメソッドに渡すパラメータです。 Unity の SendMessage では、このパラメーターは文字列型のみにすることができます。より複雑なデータを渡す必要がある場合は、他のメカニズムを使用する必要がある場合があります。

   /**
       * ReceiveJSMethod 函数用于接收来自网页的指令和消息,并将它们传递给 Unity 中的对象。
       * @param {string} methodName - 要调用的 Unity 对象的方法名
       * @param {string} message - 要传递给 Unity 对象的消息(可选)
       */
      function ReceiveJSMethod(methodName, message) {
        // 在控制台输出接收到的methodName和message,用于调试
        console.log(methodName, message);

        // 检查methodName是否不为null
        if (methodName != null) {
          // 如果message也不为null,则进行处理
          if (message != null) {
            // 将文本消息转换为base64编码
            var base64Str = btoa(
              encodeURIComponent(message).replace(
                /%([0-9A-F]{2})/g,
                function (match, p1) {
                  // 将百分比编码的序列转换回原始字符
                  return String.fromCharCode("0x" + p1);
                }
              )
            );
            // 使用Unity引擎的SendMessage方法,将methodName和base64编码的消息发送给名为"Cube"的Unity对象
            unityIns.SendMessage("Cube", methodName, base64Str);
          } else {
            // 如果没有message,只发送methodName给名为"Cube"的Unity对象
            unityIns.SendMessage("Cube", methodName);
          }
        }
      }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

8.終わり

はい、今日はここまでです~
役に立った場合は、いいね、フォロー、収集してください。質問がある場合は、コメント欄でお会いしましょう。
オリジナルであることは簡単ではありません。転載する場合は出典を明記してください。皆さんありがとうございます。