ToB企服应用市场:ToB评测及商务社交产业平台

标题: unity项目打包为webgl后应用于vue项目中(iframe模式)的数据交互 [打印本页]

作者: 缠丝猫    时间: 2024-10-19 21:34
标题: unity项目打包为webgl后应用于vue项目中(iframe模式)的数据交互
参考文章:
1.Unity打包WebGL: 导入Vue
2.unity文档-WebGL:与浏览器脚本交互
3.unity与vue交互(无第三方插件)

  
一、前期工作

1.新建.jslib文件

操作步骤:
   在 Unity 和 Vue 的交互中,jslib 插件用于实现 JavaScript 与 Unity 的桥接。它答应你在 JavaScript 中调用 Unity 的 C# 方法,或从 Unity 调用 JavaScript 函数。
  以下是为什么需要 jslib 插件以及文件位置的重要性:

这种结构确保了 JavaScript 与 Unity 之间的高效且可靠的通信。
2.新建.cs脚本

操作步骤
   当 Unity 项目导出为 WebGL 时,Unity 引擎会生成一些 JavaScript 文件,这些文件用于与浏览器进行交互。.cs 脚本可以与这些 JavaScript 文件集成,答应我们通过 Unity 的 C# 代码来调用 JavaScript 函数,大概从 JavaScript 函数中吸取消息
  3. 新建一个Text对象和button按钮对象

操作步骤
4.添加脚本空对象UIEvent

操作步骤
5.导出unity为webgl

操作步骤
1. 打开构建立置


2.选择平台

4. 设置构建目标 - 之后每次修改unity内容都要做此打包操作

构建过程

6.vue项目中引入unity打包的文件

操作步骤
public 文件夹
   用途:用于存放不会被 Webpack 处理的静态资源,如 HTML 文件、favicon、直接引用的图像等。
路径:文件在 public 文件夹中的路径将直接映射到构建后的根目录。例如,public/favicon.ico 在构建后的项目中会变成 /favicon.ico。
处理:这些文件不会经过 Webpack 处理,因此在开辟和生产环境中都保持不变。
  static文件夹(通常在 Vue CLI 3.x 及更早版本中利用)
   用途:重要用于存放静态资源,Webpack 会将这些资源复制到构建输出目录中。
路径:static 文件夹中的资源将被 Webpack 处理并优化。在构建过程中,这些文件会被移动到构建输出目录的 static 子目录中,路径会自动处理文件名的哈希值以便缓存优化。
处理:这些文件会经过 Webpack 的处理,比如版本控制和优化。
  二、从unity脚本调用js函数(vue发起,unity吸取):

(全部代码在背面可直接粘贴利用,这里针对重要模块)
焦点代码
SendMessage方法
SendMessage(objectName, methodName, value);
   其中,objectName 是场景中的对象名称;methodName 是当前附加到该对象的脚本中的方法名称;value 可以是字符串、数字,也可为空。
  三、从js调用unity脚本函数(unity发起,vue吸取):

(全部代码在背面可直接粘贴利用,这里针对重要模块)
焦点代码
window.parent.postMessage(message, targetOrigin, [transfer]);
   message: 要发送的消息,可以是字符串、对象或其他支持的数据类型。需要注意的是,发送的消息将会被序列化为 JSON 格式。
targetOrigin: 表示你希望消息发送到的目标窗口的泉源。这是一个安全机制,用于确保消息不会发送到不受信托的窗口。你可以指定特定的域(如 “https://example.com”)大概利用 “*” 作为通配符,表示答应全部泉源。
transfer (可选): 一个可选的 Transferable 对象数组,用于将某些对象的全部权从当前窗口转移到目标窗口。例如,MessagePort 对象可以用来在多个窗口之间通报消息。
   四、结果展示

在vue页面的控制台中能得到如下信息:

五、全部代码

JsTalker.cs

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. using System.Runtime.InteropServices;
  6. public class JsTalker : MonoBehaviour
  7. {
  8.     [DllImport("__Internal")]
  9.     private static extern void SayHello();
  10.     [DllImport("__Internal")]
  11.     private static extern string ReportReady();
  12.     [DllImport("__Internal")]
  13.     private static extern void GetButtonNameReady(string str);
  14.     //public TextMeshProUGUI uiText;
  15.     public Text text;
  16.     // Start is called before the first frame update
  17.     void Start()
  18.     {
  19.         ReportReady();
  20.     }
  21.     // Update is called once per frame
  22.     void Update()
  23.     {
  24.         if (Input.GetKeyUp(KeyCode.H))
  25.         {
  26.             SayHello();
  27.         }
  28.     }
  29.     public void SetToken(string token)
  30.     {
  31.         Debug.Log("token"+ token);
  32.         text.text = token;
  33.         // 强制更新 UI
  34.         Canvas.ForceUpdateCanvases();
  35.     }
  36.     // 这个方法会在按钮点击时被调用
  37.     public void OnButtonClick(Button clickedButton)
  38.     {
  39.         // 获取被点击按钮的名称
  40.         string buttonName = clickedButton.gameObject.name;
  41.         Debug.Log("被点击的按钮名称是: " + buttonName);
  42.         GetButtonNameReady(buttonName);//为什么在页面console里返回的是 48730928 ?
  43.     }
  44. }
复制代码
communication.jslib

  1. mergeInto(LibraryManager.library, {
  2.     SayHello: function () {
  3.         window.alert("hello vue");
  4.     },
  5.     ReportReady: function() {
  6.         window.ReportReady();
  7.     },
  8.        
  9.         GetButtonNameReady: function (string) {
  10.             console.log("Click-buttondata:",string);
  11.                 // 发送消息到父窗口
  12.                 window.parent.postMessage({ type: 'UNITY_BUTTON_NAME', data: UTF8ToString(string) }, '*');
  13.         }
  14. })
复制代码
打包后的index.html

  1. <!DOCTYPE html>
  2. <html lang="en-us">
  3. <head>
  4.   <meta charset="utf-8">
  5.   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  6.   <title>Unity WebGL Player</title>
  7.   <link rel="shortcut icon" href="TemplateData/favicon.ico">
  8.   <link rel="stylesheet" href="TemplateData/style.css">
  9. </head>
  10. <body>
  11.   <div id="unity-container" class="unity-desktop" style="width:100%;height: 100%;">
  12.     <canvas id="unity-canvas" width=auto height=auto tabindex="-1"></canvas>
  13.     <div id="unity-loading-bar">
  14.       <div id="unity-logo"></div>
  15.       <div id="unity-progress-bar-empty">
  16.         <div id="unity-progress-bar-full"></div>
  17.       </div>
  18.     </div>
  19.     <div id="unity-warning"> </div>
  20.     <div id="unity-footer">
  21.       <div id="unity-webgl-logo"></div>
  22.       <div id="unity-fullscreen-button"></div>
  23.       <div id="unity-build-title">HzevtSystem</div>
  24.     </div>
  25.   </div>
  26.   <script>
  27.     // var UnityToJs = {
  28.     //   /// <summary>
  29.     //   /// JS的监听方法,
  30.     //   /// 点击 xxxx 时,回传默认值。
  31.     //   JS_OnReceiveView: function (fovMin, fovMax, angleMin, angleMax) {
  32.     //     // console.log(fovMin, fovMax, angleMin, angleMax);
  33.     //     window.top.dispatchEvent(new CustomEvent('getFovDef', { detail: { 'fovMin': fovMin, 'fovMax': fovMax, 'angleMin': angleMin, 'angleMax': angleMax } }))//自定义事件,然后获取相应的数据
  34.     //   }
  35.     // }
  36.     var container = document.querySelector("#unity-container");
  37.     var canvas = document.querySelector("#unity-canvas");
  38.     var loadingBar = document.querySelector("#unity-loading-bar");
  39.     var progressBarFull = document.querySelector("#unity-progress-bar-full");
  40.     var fullscreenButton = document.querySelector("#unity-fullscreen-button");
  41.     var warningBanner = document.querySelector("#unity-warning");
  42.     // Shows a temporary message banner/ribbon for a few seconds, or
  43.     // a permanent error message on top of the canvas if type=='error'.
  44.     // If type=='warning', a yellow highlight color is used.
  45.     // Modify or remove this function to customize the visually presented
  46.     // way that non-critical warnings and error messages are presented to the
  47.     // user.
  48.     function unityShowBanner(msg, type) {
  49.       function updateBannerVisibility() {
  50.         warningBanner.style.display = warningBanner.children.length ? 'block' : 'none';
  51.       }
  52.       var div = document.createElement('div');
  53.       div.innerHTML = msg;
  54.       warningBanner.appendChild(div);
  55.       if (type == 'error') div.style = 'background: red; padding: 10px;';
  56.       else {
  57.         if (type == 'warning') div.style = 'background: yellow; padding: 10px;';
  58.         setTimeout(function () {
  59.           warningBanner.removeChild(div);
  60.           updateBannerVisibility();
  61.         }, 5000);
  62.       }
  63.       updateBannerVisibility();
  64.     }
  65.     var buildUrl = "Build";
  66.     var loaderUrl = buildUrl + "/unityweb.loader.js";
  67.     var config = {
  68.       dataUrl: buildUrl + "/unityweb.data",
  69.       frameworkUrl: buildUrl + "/unityweb.framework.js",
  70.       codeUrl: buildUrl + "/unityweb.wasm",
  71.       streamingAssetsUrl: "StreamingAssets",
  72.       companyName: "DefaultCompany",
  73.       productName: "HzevtSystem",
  74.       productVersion: "1.0",
  75.       showBanner: unityShowBanner,
  76.     };
  77.     // By default, Unity keeps WebGL canvas render target size matched with
  78.     // the DOM size of the canvas element (scaled by window.devicePixelRatio)
  79.     // Set this to false if you want to decouple this synchronization from
  80.     // happening inside the engine, and you would instead like to size up
  81.     // the canvas DOM size and WebGL render target sizes yourself.
  82.     // config.matchWebGLToCanvasSize = false;
  83.     if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
  84.       // Mobile device style: fill the whole browser client area with the game canvas:
  85.       var meta = document.createElement('meta');
  86.       meta.name = 'viewport';
  87.       meta.content = 'width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, shrink-to-fit=yes';
  88.       document.getElementsByTagName('head')[0].appendChild(meta);
  89.       container.className = "unity-mobile";
  90.       canvas.className = "unity-mobile";
  91.       // To lower canvas resolution on mobile devices to gain some
  92.       // performance, uncomment the following line:
  93.       // config.devicePixelRatio = 1;
  94.       canvas.style.width = window.innerWidth + 'px';
  95.       canvas.style.height = window.innerHeight + 'px';
  96.       unityShowBanner('暂不支持移动端');
  97.     } else {
  98.       // Desktop style: Render the game canvas in a window that can be maximized to fullscreen:
  99.       canvas.style.width = "100%";
  100.       canvas.style.height = "100%";
  101.     }
  102.     loadingBar.style.display = "block";
  103.     var script = document.createElement("script");
  104.     script.src = loaderUrl;
  105.     script.onload = () => {
  106.       createUnityInstance(canvas, config, (progress) => {
  107.         progressBarFull.style.width = 100 * progress + "%";
  108.       }).then((unityInstance) => {
  109.         console.log('unityInstance', unityInstance);
  110.         console.log('window', window);
  111.         // 绑定unityInstance
  112.         window.unityInstance = unityInstance;
  113.         console.log('window.unityInstance', window.unityInstance);
  114.         loadingBar.style.display = "none";
  115.         fullscreenButton.onclick = () => {
  116.           unityInstance.SetFullscreen(1);
  117.         };
  118.       }).catch((message) => {
  119.         alert(message);
  120.       });
  121.     };
  122.     document.body.appendChild(script);
  123.    
  124.     // unity调用函数
  125.     // vue发起 unity接收
  126.     window.ReportReady = () => {
  127.         // window.top.dispatchEvent(new CustomEvent())
  128.         send({
  129.           id: 1,
  130.           value: 2
  131.         })
  132.       }
  133.     function send(obj) {
  134.       unityInstance.SendMessage('modelButton1', 'SetToken', JSON.stringify(obj))
  135.     }
  136.   </script>
  137. </body>
  138. </html>
复制代码
vue页面

  1. <template>
  2.   <div style="width: 100%; height: 100%">
  3.     <div @click="send">给unity发送数据</div>
  4.     <iframe ref="iframe" width="100%" height="100%" scrolling="no" src="/static/Unitys/web/index.html" frameborder="0"></iframe>
  5.   </div>
  6. </template>
  7. <script>
  8. export default {
  9.   name: "testUnityAScene",
  10.   data() {
  11.     return {
  12.       nodeList: [
  13.         { id: 11, name: "node1" },
  14.         { id: 22, name: "node2" },
  15.         { id: 33, name: "node3" },
  16.       ],
  17.     };
  18.   },
  19.   mounted() {
  20.     console.log('this.$refs.iframe.contentWindow', this.$refs.iframe.contentWindow);
  21.     // this.$refs.iframe.contentWindow.unityInstance.SendMessage('WebInvoker', 'Unity_InsertNaviPoint', this.nodeList.length);
  22.     window.addEventListener('message', this.handleMessage, false);
  23.   },
  24.   methods: {
  25.     send() {
  26.       // 发送数据
  27.       this.$refs.iframe.contentWindow.send({
  28.           id: 111,
  29.           value: 222
  30.         })
  31.     },
  32.     handleMessage(event) {
  33.       console.log('event11111111111:',event);
  34.       // 检查消息类型
  35.       if (event.data.type === 'UNITY_BUTTON_NAME') {
  36.         console.log('Received button name from Unity:', event.data.data);
  37.         // 在此处理按钮名称
  38.       }
  39.     }
  40.   },
  41.   beforeDestroy() {
  42.     window.removeEventListener('message', this.handleMessage, false);
  43.   },
  44. };
  45. </script>
  46. <style>
  47. </style>
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4