Обмен технологиями

Unity WebGL встраивает внешние веб-страницы и взаимодействует

2024-07-12

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

1. Введение

Недавно при работе над проектом я столкнулся с необходимостью встроить UnityWebGL в веб-страницу, а UnityWebGL должен реагировать при нажатии кнопки на веб-странице.Пропустить новую часть проекта напрямую

2. Конечный эффект

webglResult.gif

3. Основные настройки

  • Установите платформу экспорта на WebGL.
    Вставленное изображение 20240527102413
  • Проверьте настройки проигрывателя -> Настройки публикации. Data Caching иDecompression Fallback Ссылка ниже является официальным объяснением.
    Data Caching Проще говоря, данные кэшируются локально и при следующем открытии вы сможете напрямую войти в игру без скачивания.
    Decompression Fallback Если есть невозможность парсить gz-файлы, ошибки конфигурации веб-сервера и т.п., необходимо отметить эту опцию.
    Unity - Руководство: Настройки проигрывателя WebGL (unity3d.com)
    Вставленное изображение 20240527102930

4. Написание и экспорт кода

  • Сцена настроена следующим образом (вы можете создавать сцены под свои нужды)
    Вставленное изображение 20240527110105
  • Кодовая часть (монтируем код на созданный Куб)

Примечание. Метод должен быть общедоступным, иначе он не будет доступен.

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浏览器 , для загрузки требуются определенные параметры конфигурации.Открыть webgl в Firefox_Открыть webgl в Firefox-Блог CSDN

5. Пример веб-страницы

Учитывая, что некоторые друзья могут не знать, как писать веб-страницы, автор предоставляет простой шаблон веб-страницы, который каждый может протестировать.

Инструкция по использованию: Создайте новый текстовый файл, вставьте в него следующий код, сохраните его и измените суффикс файла на.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 и веб-страницы в одну папку, как показано ниже (этот шаг в основном предназначен для удобства управления, вам этого делать не нужно)
    Вставленное изображение 20240527114742
  • Используйте IDE, чтобы открыть веб-страницу и найти место, отмеченное красным прямоугольником в приведенном ниже коде.
    Вставленное изображение 20240527114359
  • Замените содержимое тега div следующим кодом. Если ваш проект WebGL развернут на сервере, вы можете заменить содержимое тега iframe следующим кодом.src Просто измените ссылку на адрес сервера. (Информацию об iframe см.HTML-фрейм (w3school.com.cn)) сохраняйте и используйтеFirefox浏览器Откройте веб-страницу, и проекты, развернутые на сервере, можно будет открыть в любом браузере, поддерживающем 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. Веб-страница вызывает метод Unity.

  • Найдите место, отмеченное красной рамкой в ​​приведенном ниже коде.
    Вставленное изображение 20240527121614
  • Замените содержимое тега скрипта следующим кодом (код относительно простой и имеет комментарии, поэтому я не буду его слишком подробно объяснять):

Уведомление: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 (файл index.html на рисунке ниже).
    Вставленное изображение 20240527142351
  • Найдите тег скрипта и найдите под этим тегом код инициализации загрузчика. И добавьте код в красное поле.
    Вставленное изображение 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Методы. Это позволяет вам вызывать определенные методы игровых объектов в вашей сцене Unity из кода JavaScript.

Уведомление:SendMessage Метод имеет три параметра:
Имя целевого объекта: это имя игрового объекта в сцене. Для этого объекта определен метод, который вы хотите вызвать.
Имя метода: это имя метода, который вы хотите вызвать. Это должен быть общедоступный метод в скрипте целевого объекта.
Параметры: это параметры, которые вы хотите передать методу. В SendMessage Unity этот параметр может иметь только строковый тип. Если вам нужно передать более сложные данные, возможно, вам придется использовать другие механизмы.

   /**
       * 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. Конец

Ладно, на сегодня всё~
Если это было полезно для вас, вы можете поставить лайк, подписаться и собрать его. Если у вас есть вопросы, увидимся в области комментариев ~
Нелегко быть оригинальным. Если перепечатываете, пожалуйста, укажите источник. Всем спасибо~