Compartilhamento de tecnologia

Unity WebGL incorpora páginas da web front-end e se comunica

2024-07-12

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

1. Introdução

Recentemente, ao trabalhar em um projeto, encontrei a necessidade de incorporar o UnityWebGL em uma página da web, e o UnityWebGL precisa responder ao clicar em um botão na página da web.Ignore a nova parte do projeto diretamente

2. Efeito final

Resultadowebgl.gif

3. Configurações básicas

  • Defina a plataforma de exportação para WebGL
    Imagem colada 20240527102413
  • Verifique as configurações do player -> Configurações de publicação Data Caching eDecompression Fallback O link abaixo é a explicação oficial.
    Data Caching Simplificando, os dados são armazenados em cache localmente e na próxima vez que você abri-los, você pode entrar diretamente no jogo sem fazer download.
    Decompression Fallback Se não for possível analisar arquivos gz, erros de configuração do servidor web, etc., você precisará marcar esta opção.
    Unity - Manual: Configurações do player WebGL (unity3d.com)
    Imagem colada 20240527102930

4. Escrita e exportação de código

  • A cena é configurada da seguinte forma (você pode criar cenas de acordo com suas necessidades)
    Imagem colada 20240527110105
  • Parte do código (montar o código no cubo criado)

Nota: O método deve ser público, caso contrário não será acessível

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
  • Exportar WebGL (basta aguardar a conclusão da exportação)
    Imagem colada 20240527110452

Se quiser navegar pelos arquivos compactados localmente, você precisará baixá-los. Firefox浏览器 , o download requer alguns parâmetros de configuração específicos.Abra o webgl no Firefox_Abra o webgl no Firefox-CSDN Blog

5. Exemplo de página da web

Considerando que alguns amigos podem não saber escrever páginas da web, o autor fornece um modelo simples de página da web para que todos possam testar.

Instruções de uso: Crie um novo arquivo de texto, cole o seguinte código nele, salve-o e altere o sufixo do arquivo para.html
Imagem colada 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. Incorporar WebGL

  • Crie uma pasta e coloque o WebGL empacotado e as páginas da web na mesma pasta, conforme mostrado abaixo (esta etapa é principalmente para facilitar o gerenciamento, você não precisa fazer isso)
    Imagem colada 20240527114742
  • Use o IDE para abrir a página da web e encontre o local marcado pela caixa vermelha no código abaixo.
    Imagem colada 20240527114359
  • Substitua o conteúdo da tag div pelo código a seguir. Se o seu projeto WebGL tiver sido implementado no servidor, você poderá substituir o conteúdo da tag iframe pelo código a seguir.src Basta alterar o link para o endereço do servidor. (Para obter informações sobre iframe, consulteIframe HTML (w3school.com.cn)) salvar e usarFirefox浏览器Abra uma página da web e os projetos que foram implantados no servidor poderão ser abertos com qualquer navegador que suporte 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

Imagem colada 20240527115228
Imagem colada 20240527115718

resultado em execução

7. A página da Web chama o método Unity

  • Encontre o local marcado pela caixa vermelha no código abaixo
    Imagem colada 20240527121614
  • Substitua o conteúdo da tag script pelo código a seguir (o código é relativamente simples e tem comentários, então não vou explicar muito)

Perceber:methodName Deve ser consistente com o nome do método no Unity, caso contrário o método não será encontrado.

    // 获取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

Imagem colada 20240527122058

  • Após concluir as etapas acima, use o IDE para abrir a página WebGL (arquivo index.html na imagem abaixo)
    Imagem colada 20240527142351
  • Encontre a tag do script e o código para inicializar o carregador nesta tag. E adicione o código na caixa vermelha.
    Imagem colada 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
  • Crie o código para enviar mensagens para o Unity Aqui explicamos brevemente o que é usado no código.SendMessageMétodos Isso permite que você chame métodos específicos em objetos de jogo na cena do Unity a partir do código JavaScript.

Perceber:SendMessage O método possui três parâmetros:
Nome do objeto alvo: Este é o nome do objeto do jogo na cena. O método que você deseja chamar é definido neste objeto.
Nome do Método: Este é o nome do método que você deseja chamar, deve ser um método público no script do objeto de destino.
Parâmetros: Estes são os parâmetros que você deseja passar para o método. No SendMessage do Unity, esse parâmetro só pode ser do tipo string. Se precisar passar dados mais complexos, talvez seja necessário usar outros mecanismos.

   /**
       * 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. Fim

Ok, isso é tudo por hoje~
Se for útil para você, você pode curtir, seguir e coletar. Se tiver alguma dúvida, nos vemos na área de comentários ~.
Não é fácil ser original. Se você reimprimir, indique a fonte. Obrigado a todos.