unity项目打包为webgl后应用于vue项目中(iframe模式)的数据交互

news2024/11/14 17:08:22

参考文章:
1.Unity打包WebGL: 导入Vue

2.unity文档-WebGL:与浏览器脚本交互

3.unity与vue交互(无第三方插件)

目录

  • 一、前期工作
    • 1.新建.jslib文件
    • 2.新建.cs脚本
    • 3. 新建一个Text对象和button按钮对象
    • 4.添加脚本空对象UIEvent
    • 5.导出unity为webgl
    • 6.vue项目中引入unity打包的文件
  • 二、从unity脚本调用js函数(vue发起,unity接收):
  • 三、从js调用unity脚本函数(unity发起,vue接收):
  • 四、结果展示
  • 五、全部代码
    • JsTalker.cs
    • communication.jslib
    • 打包后的index.html
    • vue页面

一、前期工作

1.新建.jslib文件

操作步骤

  1. 在unity项目的Assets/Plugins 文件夹下新建一个txt文本文档,保存并关掉文档;
  2. 将文档命名为 communication.jslib ,保存;
  3. 双击 communication.jslib 文件,用其它工具打开编辑即可(我这里用的是HBuilder),编辑内容后面有介绍(三、从js调用unity脚本函数)。

在 Unity 和 Vue 的交互中,jslib 插件用于实现 JavaScript 与 Unity 的桥接。它允许你在 JavaScript 中调用 Unity 的 C# 方法,或从 Unity 调用 JavaScript 函数。

以下是为什么需要 jslib 插件以及文件位置的重要性:

  • 桥接功能jslib 插件使得 JavaScript 和 Unity 之间可以进行函数调用,这在处理 WebGL 平台时尤其重要。Unity 的 WebGL 构建运行在浏览器中,而浏览器环境与 Unity 的运行环境(C#)是隔离的,jslib 通过定义如何在两者之间传递数据和调用方法来实现桥接。

  • 函数调用:通过在 jslib 中定义的函数,你可以从 JavaScript 直接调用 Unity 的 C# 方法,或者反向操作。这种方式简化了两者之间的通信,使得复杂的数据交换和操作变得可行。

  • 文件位置:将 jslib 文件放置在 Unity 项目的 Assets/Plugins 文件夹中的 WebGL 子文件夹下是为了确保 Unity 能够识别和正确加载这些插件文件。Unity 在构建 WebGL 项目时,会自动将 Plugins 文件夹中的 jslib 文件包含在内,并按照预期执行其中定义的 JavaScript 代码。

这种结构确保了 JavaScript 与 Unity 之间的高效且可靠的通信。

2.新建.cs脚本

操作步骤

  1. 在unity项目的Assets 文件夹下新建一个script文件夹,在script文件夹中新建一个C# Script脚本,命名为JsTalker.cs

当 Unity 项目导出为 WebGL 时,Unity 引擎会生成一些 JavaScript 文件,这些文件用于与浏览器进行交互。.cs 脚本可以与这些 JavaScript 文件集成,允许我们通过 Unity 的 C# 代码来调用 JavaScript 函数,或者从 JavaScript 函数中接收消息

3. 新建一个Text对象和button按钮对象

操作步骤

  1. 在unity中的Hierarchy工作区中创建一个可回显获取数据的UI对象,这里以Text对象为例;新建button对象同理,并给button对象重命名为modelButton1
    在这里插入图片描述

  2. 设置Text对象样式为白色,目的是为了显眼些。
    在这里插入图片描述

4.添加脚本空对象UIEvent

操作步骤

  1. 在Hierarchy工作区中鼠标右键 - Create Empty - 重命名GameObject为UIEvent - 将JsTalker.cs 拖拽移入至UIEvent对象里。
  2. modelButton1添加按钮onClick点击事件,为后面点击按钮传参做准备;并添加JsTalker.cs脚本。
    在这里插入图片描述

5.导出unity为webgl

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

  • 在 Unity 编辑器中,点击顶部菜单栏的 File。
  • 选择 Build Settings,这将打开构建设置窗口。

在这里插入图片描述
2.选择平台

  • 在构建设置窗口中,会看到一个平台列表。在这个列表中选择 WebGL。
  • 如果 WebGL 平台尚未安装,可以点击 Add Open Scenes 或者在右下角点击 Switch Platform 进行切换。Unity 会自动下载和安装 WebGL 支持的必要组件。
    在这里插入图片描述
    3. 设置 Player 设置
  • 在 Build Settings 窗口中,点击 Player Settings 按钮。这会打开 Inspector 面板中的 Player 设置。
  • 在 Player Settings 面板中,我们可以配置 WebGL 特有的设置,如分辨率、质量、图标等。
    • Resolution and Presentation:设置 WebGL 输出的分辨率和全屏模式。
    • Other Settings:配置 WebGL 的各种参数,例如内存大小、脚本运行时等。
    • Publishing Settings:设置压缩和加密选项,以便优化构建的大小和性能。
      在这里插入图片描述

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

  • 确保在 Build Settings 窗口中选择了 WebGL 作为目标平台。
  • 点击 Build 按钮,选择一个保存位置,然后 Unity 会开始构建过程。

构建过程

  • Unity 会将我们的项目打包为一个 WebGL 兼容的格式,并生成一个包含 HTML、JavaScript 和数据文件的文件夹。构建过程可能需要一些时间,具体取决于项目的复杂性和你的计算机性能。生成的文件如下:
    在这里插入图片描述

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

操作步骤

  1. 在 Vue 项目根目录的public文件夹 static文件夹下创建 unity 文件夹。
  2. 将unity刚刚打包的文件复制public/unity 文件夹或 static/unity 文件夹下。
    之后每次修改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接收):

(全部代码在后面可直接粘贴使用,这里针对主要模块)
核心代码

  1. 编辑JsTalker.cs脚本

    //public TextMeshProUGUI uiText;//这个是新版的Text组件对象,用这个就要确保引用了 TextMeshPro 的命名空间using TMPro;
    public Text text;//这个是旧版的Text对象
    public void SetToken(string token)
    {
        Debug.Log("token"+ token);
        text.text = token;//改变Text对象的文本内容
        // 强制更新 UI
        Canvas.ForceUpdateCanvases();
    }
    
  2. 编辑打包后的index.html文件

    	// unity调用函数
        // vue发起 unity接收
        window.ReportReady = () => {
            send({
              id: 1,
              value: 2
            })
          }
        function send(obj) {
          unityInstance.SendMessage('modelButton1', 'SetToken', JSON.stringify(obj))
        }
    

SendMessage方法
SendMessage(objectName, methodName, value);

其中,objectName 是场景中的对象名称;methodName 是当前附加到该对象的脚本中的方法名称;value 可以是字符串、数字,也可为空。

三、从js调用unity脚本函数(unity发起,vue接收):

(全部代码在后面可直接粘贴使用,这里针对主要模块)
核心代码

  1. unity中的.jslib定义方法GetButtonNameReady(string str),使用以下方法跨文档传递,将参数发送到父窗口并定义type;

    GetButtonNameReady: function (string) {
    	    console.log("Click-buttondata:",string);
    		// 发送消息到父窗口
    		window.parent.postMessage({ type: 'UNITY_BUTTON_NAME', data: UTF8ToString(string) }, '*');
    }
    

window.parent.postMessage(message, targetOrigin, [transfer]);

message: 要发送的消息,可以是字符串、对象或其他支持的数据类型。需要注意的是,发送的消息将会被序列化为 JSON 格式。
targetOrigin: 表示你希望消息发送到的目标窗口的来源。这是一个安全机制,用于确保消息不会发送到不受信任的窗口。你可以指定特定的域(如 “https://example.com”)或者使用 “*” 作为通配符,表示允许所有来源。
transfer (可选): 一个可选的 Transferable 对象数组,用于将某些对象的所有权从当前窗口转移到目标窗口。例如,MessagePort 对象可以用来在多个窗口之间传递消息。

  1. unity中的按钮点击事件里使用JsTalker.cs组件,脚本中添加点击按钮后传按钮名称参数;
    using System.Runtime.InteropServices;
    [DllImport("__Internal")]
    private static extern void GetButtonNameReady(string str);
    public void OnButtonClick(Button clickedButton)
    {
        // 获取被点击按钮的名称
        string buttonName = clickedButton.gameObject.name;
        Debug.Log("被点击的按钮名称是: " + buttonName);
        GetButtonNameReady(buttonName);//为什么在页面console里返回的是 48730928 ?
    }
    
  2. unity中选中modelButton1,设置其onClick添加UIEvent事件,并选择GetButtonNameReady方法
    在这里插入图片描述
  3. vue页面中使用监听message获取按钮名称
    'UNITY_BUTTON_NAME'是在.jslib文件中自定义的。
    export default {
      mounted() {
        window.addEventListener('message', this.handleMessage, false);
      },
      methods: {
        handleMessage(event) {
          // 检查消息类型
          if (event.data.type === 'UNITY_BUTTON_NAME') {
            console.log('Received button name from Unity:', event.data.data);
            // 在此处理按钮名称
          }
        }
      },
      beforeDestroy() {
        window.removeEventListener('message', this.handleMessage, false);
      }
    }
    

四、结果展示

在vue页面的控制台中能获得如下信息:
在这里插入图片描述

五、全部代码

JsTalker.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;

public class JsTalker : MonoBehaviour
{
    [DllImport("__Internal")]
    private static extern void SayHello();
    [DllImport("__Internal")]
    private static extern string ReportReady();


    [DllImport("__Internal")]
    private static extern void GetButtonNameReady(string str);

    //public TextMeshProUGUI uiText;
    public Text text;

    // Start is called before the first frame update
    void Start()
    {
        ReportReady();

    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyUp(KeyCode.H))
        {
            SayHello();

        }
    }

    public void SetToken(string token)
    {
        Debug.Log("token"+ token);
        text.text = token;
        // 强制更新 UI
        Canvas.ForceUpdateCanvases();
    }

    // 这个方法会在按钮点击时被调用
    public void OnButtonClick(Button clickedButton)
    {
        // 获取被点击按钮的名称
        string buttonName = clickedButton.gameObject.name;
        Debug.Log("被点击的按钮名称是: " + buttonName);
        GetButtonNameReady(buttonName);//为什么在页面console里返回的是 48730928 ?
    }
}

communication.jslib

mergeInto(LibraryManager.library, {

    SayHello: function () {
        window.alert("hello vue");
    },

    ReportReady: function() {
        window.ReportReady();
    },
	
	GetButtonNameReady: function (string) {
	    console.log("Click-buttondata:",string);
		// 发送消息到父窗口
		window.parent.postMessage({ type: 'UNITY_BUTTON_NAME', data: UTF8ToString(string) }, '*');
	}
})

打包后的index.html

<!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</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" style="width:100%;height: 100%;">
    <canvas id="unity-canvas" width=auto height=auto tabindex="-1"></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-warning"> </div>
    <div id="unity-footer">
      <div id="unity-webgl-logo"></div>
      <div id="unity-fullscreen-button"></div>
      <div id="unity-build-title">HzevtSystem</div>
    </div>
  </div>
  <script>

    // var UnityToJs = {
    //   /// <summary>
    //   /// JS的监听方法,
    //   /// 点击 xxxx 时,回传默认值。
    //   JS_OnReceiveView: function (fovMin, fovMax, angleMin, angleMax) {
    //     // console.log(fovMin, fovMax, angleMin, angleMax);
    //     window.top.dispatchEvent(new CustomEvent('getFovDef', { detail: { 'fovMin': fovMin, 'fovMax': fovMax, 'angleMin': angleMin, 'angleMax': angleMax } }))//自定义事件,然后获取相应的数据
    //   }
    // }

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

    // Shows a temporary message banner/ribbon for a few seconds, or
    // a permanent error message on top of the canvas if type=='error'.
    // If type=='warning', a yellow highlight color is used.
    // Modify or remove this function to customize the visually presented
    // way that non-critical warnings and error messages are presented to the
    // user.
    function unityShowBanner(msg, type) {
      function updateBannerVisibility() {
        warningBanner.style.display = warningBanner.children.length ? 'block' : 'none';
      }
      var div = document.createElement('div');
      div.innerHTML = msg;
      warningBanner.appendChild(div);
      if (type == 'error') div.style = 'background: red; padding: 10px;';
      else {
        if (type == 'warning') div.style = 'background: yellow; padding: 10px;';
        setTimeout(function () {
          warningBanner.removeChild(div);
          updateBannerVisibility();
        }, 5000);
      }
      updateBannerVisibility();
    }

    var buildUrl = "Build";
    var loaderUrl = buildUrl + "/unityweb.loader.js";
    var config = {
      dataUrl: buildUrl + "/unityweb.data",
      frameworkUrl: buildUrl + "/unityweb.framework.js",
      codeUrl: buildUrl + "/unityweb.wasm",
      streamingAssetsUrl: "StreamingAssets",
      companyName: "DefaultCompany",
      productName: "HzevtSystem",
      productVersion: "1.0",
      showBanner: unityShowBanner,
    };

    // 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)) {
      // Mobile device style: fill the whole browser client area with the game canvas:

      var meta = document.createElement('meta');
      meta.name = 'viewport';
      meta.content = 'width=device-width, height=device-height, initial-scale=1.0, user-scalable=no, shrink-to-fit=yes';
      document.getElementsByTagName('head')[0].appendChild(meta);
      container.className = "unity-mobile";
      canvas.className = "unity-mobile";

      // To lower canvas resolution on mobile devices to gain some
      // performance, uncomment the following line:
      // config.devicePixelRatio = 1;

      canvas.style.width = window.innerWidth + 'px';
      canvas.style.height = window.innerHeight + 'px';
      unityShowBanner('暂不支持移动端');
    } else {
      // Desktop style: Render the game canvas in a window that can be maximized to fullscreen:

      canvas.style.width = "100%";
      canvas.style.height = "100%";
    }

    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) => {
        console.log('unityInstance', unityInstance);
        console.log('window', window);
        // 绑定unityInstance
        window.unityInstance = unityInstance;
        console.log('window.unityInstance', window.unityInstance);

        loadingBar.style.display = "none";
        fullscreenButton.onclick = () => {
          unityInstance.SetFullscreen(1);
        };
      }).catch((message) => {
        alert(message);
      });
    };

    document.body.appendChild(script);
    
    // unity调用函数
    // vue发起 unity接收
    window.ReportReady = () => {
        // window.top.dispatchEvent(new CustomEvent())
        send({
          id: 1,
          value: 2
        })
      }
    function send(obj) {
      unityInstance.SendMessage('modelButton1', 'SetToken', JSON.stringify(obj))
    }

  </script>
</body>

</html>

vue页面

<template>
  <div style="width: 100%; height: 100%">
    <div @click="send">给unity发送数据</div>
    <iframe ref="iframe" width="100%" height="100%" scrolling="no" src="/static/Unitys/web/index.html" frameborder="0"></iframe>
  </div>
</template>

<script>
export default {
  name: "testUnityAScene",
  data() {
    return {
      nodeList: [
        { id: 11, name: "node1" },
        { id: 22, name: "node2" },
        { id: 33, name: "node3" },
      ],
    };
  },
  mounted() {
    console.log('this.$refs.iframe.contentWindow', this.$refs.iframe.contentWindow);
    // this.$refs.iframe.contentWindow.unityInstance.SendMessage('WebInvoker', 'Unity_InsertNaviPoint', this.nodeList.length);

    window.addEventListener('message', this.handleMessage, false);
  },
  methods: {
    send() {
      // 发送数据
      this.$refs.iframe.contentWindow.send({
          id: 111,
          value: 222
        })
    },
    handleMessage(event) {
      console.log('event11111111111:',event);
      // 检查消息类型
      if (event.data.type === 'UNITY_BUTTON_NAME') {
        console.log('Received button name from Unity:', event.data.data);
        // 在此处理按钮名称
      }
    }
  },
  beforeDestroy() {
    window.removeEventListener('message', this.handleMessage, false);
  },
};
</script>

<style>
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2043565.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-配置加载顺序

目录 前言 样例 内部配置加载顺序 ​ 样例 小结 前言 我之前写的配置文件&#xff0c;都是放在resources文件夹&#xff0c;根据当前目录下&#xff0c;优先级的高低&#xff0c;判断谁先被加载。但实际开发中&#xff0c;我们写的配置文件并不是&#xff0c;都放…

利用CICD管道和MLOps自动化微调、部署亚马逊云科技上的AI大语言模型

项目简介&#xff1a; 小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案&#xff0c;帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践&#xff0c;并应用到自己的日常工作里。 本次介绍的是如何在亚马逊云科技利用CodeP…

DeepLearning.AI课程:从代码层面理解预训练大语言模型(Pretraining LLMs)

本文是学习 https://www.deeplearning.ai/short-courses/pretraining-llms/ 这门课的学习笔记。 What you’ll learn in this course In Pretraining LLMs you’ll explore the first step of training large language models using a technique called pretraining. You’ll …

如何从Mac 电脑恢复已删除的文件

您是否曾经不小心从Mac中删除了文件或文件夹&#xff0c;然后后来意识到您确实需要它&#xff1f;或者你有没有清空过你的垃圾桶&#xff0c;片刻后才意识到你不小心也从那里删除了一些重要文件&#xff1f;如果是&#xff0c;那么这篇博文就是为你准备的&#xff01; 今天&am…

书籍分享:【矩阵力量】豆瓣评分高达9.6,看完感叹《矩阵论》又白学了

书籍分享&#xff1a;【矩阵力量】豆瓣评分高达9.6&#xff0c;看完感叹《矩阵论》又白学了 《矩阵力量》简要介绍书籍下载链接 《矩阵力量》简要介绍 《矩阵力量》是姜伟生精心编写的线性代数的深度理解之作&#xff0c;作者将抽象的线性代数概念用通俗易懂的语言和大量生动形…

【过程管理】项目需求管理规程(Word原件)

在软件开发的过程中&#xff0c;开发人员与用户之间往往忽视有效的信息沟通&#xff0c;这常常导致开发出的软件无法满足用户的实际需求&#xff0c;进而引发不必要的返工。返工不仅为开发人员带来技术上的困扰&#xff0c;增加了人力和物力的消耗&#xff0c;还会对软件的整体…

tiktok 搜索翻页

这几天有小伙伴问tk的搜索接口的问题, 一个是搜索热门接口请求返回 {“status_code”: 0},这个使用curl_cffi的requests库改一下指纹请求就行了。 再一个就是翻页问题 细心一些比对一下翻页参数都能做到的(小伙伴以为只改个offset就完事了) 要不然你只能得到这样的结果:…

实现异形(拱形)轮播图

项目需要实现如上图所示的轮播图。 实现思路&#xff1a; 1.项目引入使用普通轮播图。 2.根据轮播图个数&#xff0c;动态给可视范围的第一个轮播图和最后一个轮播图添加样式。 代码实现&#xff1a; 经调研&#xff0c;使用slick轮播图&#xff08;官网地址 https://kenwheel…

经纬恒润再度受邀参加中国一汽红旗供应链创新科技展

中国一汽红旗“技领时代&#xff0c;智创未来”第六届供应链创新科技展在长春一汽总部旗境空间隆重举行&#xff0c;经纬恒润作为中国一汽战略合作伙伴及理事会成员受邀出席&#xff0c;携最新汽车电子研发成果亮相科技展&#xff0c;副总经理范成建博士受邀出席本次开幕式。 本…

电子电气架构 --- 整车电源管理

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

【MySQL进阶】事务、存储引擎、索引、SQL优化、锁

一、事务 1.概念 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向 系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 例子&#xff1a;转账&#xff0c;要求扣钱和进账…

Mysql 离线版下载安装-(详细版)

Mysql 离线版下载安装-(详细版) 文章目录 Mysql 离线版下载安装-(详细版)1.0 下载地址2.0 解压到本地2.0.1 配置环境变量2.0.2 新建mysql配置文件ini2.0.3使用管理员启动 cmd 3.0 初始化密码忘记了4.0 修改初始化密码5.0 使用可视化工具登录Mysql 1.0 下载地址 地址&#xff1…

stm32使用笔记

stm32外设使用 1. adc使用2. uart使用 1. adc使用 参考文章 static void MX_Adc_DMA_Init(void) {/* DMA controller clock enable */__HAL_RCC_DMA1_CLK_ENABLE();/* DMA interrupt init *//* DMA1_Channel1_IRQn interrupt configuration */HAL_NVIC_SetPriority(DMA1_Cha…

人工智能应用中的恐怖谷效应是什么?

人工智能应用中的恐怖谷效应是什么&#xff1f; 引言 随着人工智能、机器人技术和计算机图形学的发展&#xff0c;越来越逼真的人形机器人、虚拟角色和动画形象开始出现。然而&#xff0c;尽管这些技术进步令人惊叹&#xff0c;它们也带来了一个有趣而复杂的心理现象&#xf…

应急响应:Linux 入侵排查思路.

什么是应急响应. 一个组织为了 应对 各种网络安全 意外事件 的发生 所做的准备 以及在 事件发生后 所采取的措施 。说白了就是别人攻击你了&#xff0c;你怎么把这个攻击还原&#xff0c;看看别人是怎么攻击的&#xff0c;然后你如何去处理&#xff0c;这就是应急响应。 目录&…

引领企业全球化发展 极光亮相华为亚太ICT峰会2024·泰国

近日&#xff0c;华为亚太ICT峰会2024泰国正式开幕&#xff0c;极光&#xff08;Aurora Mobile&#xff0c;纳斯达克股票代码&#xff1a;JG&#xff09;凭借其创新的技术实力与前瞻性的产品布局&#xff0c;受邀出席本次活动。会上&#xff0c;极光展示了其全域消息通知解决方…

【C语言篇】C语言常考及易错题整理DAY1

文章目录 C语言常考及易错题整理选择题全局、局部和静态变量#define与typedef转义字符操作符循环其他 编程题计算日期到天数转换柯尼希定理旋转数组的最小数字描述错误的集合整数转换密码检查 C语言常考及易错题整理 选择题 全局、局部和静态变量 执行下面程序&#xff0c;正…

表操作数据库练习

1.一个关系数据库文件中的各条记录 &#xff08; &#xff09; A.前后顺序不能任意颠倒&#xff0c;一定要按照输入的顺序排列 B.前后顺序可以任意颠倒&#xff0c;不影响库中的数据关系 C.前后顺序可以任意颠倒&#xff0c;但排列顺序不同&#xff0c;统计处理的结果就可…

人工智能-自然语言处理(NLP)

人工智能-自然语言处理&#xff08;NLP&#xff09; 1. NLP的基础理论1.1 语言模型&#xff08;Language Models&#xff09;1.1.1 N-gram模型1.1.2 词嵌入&#xff08;Word Embeddings&#xff09;1.1.2.1 词袋模型&#xff08;Bag of Words, BoW&#xff09;1.1.2.2 TF-IDF&a…

SDL 锁屏视频卡死bug原因

最近在封装播放库&#xff0c;我用的是FFMPEGSDL库封装&#xff0c;这个库其实用起来不难&#xff0c;因为网上可供参考的资源也多&#xff0c;所以我自己也封装了一个&#xff0c;但是播放视频时只要我电脑一锁屏再重新打开&#xff0c;我靠视频卡住不动了&#xff0c;我调试看…