从0到1实现一个RS蓝图系统-概念提出技术栈选型

请不要自我设限,真正好的人生态度,是现在就做,不等、不靠、不懒惰。

——小野《改变力》

一、什么是蓝图?

  • 蓝图(BluePrint) 是Epic Games 针对虚幻4引擎开发的可视化脚本语言。
  • 当你使用蓝图的时候,其实就是在编写代码,只不过它采用更加可视化的方法,它不需要你编写任何C++代码,只需要将不同功能的蓝图节点连接起来,就能实现想要的功能。
  • 蓝图是一种允许你以可视化的方式创建内容的系统,你所构建的内容通常称作“蓝图文件(Blueprints)”。
  • 你可以创建许多不同类型的蓝图,蓝图相当于游戏内容的容器,它包含了许多基本单元,这些单元被称之为“组件Components”。举个例子:一个汽车蓝图,就可以包含车架组件、车轮组件、引擎组件等诸如此类的组件,它门还能包含脚本功能,让油门被踩下时,引擎驱动汽车前进,但我们也可以不编写任何功能,只不过汽车不知道如何前进而已。
  • 蓝图还可以包含数据,而且数据是可以调整的。
  • 蓝图节点的本质:将功能不同的节点连接在一起。

二、实现原理

  1. 节点和连接
    开发者通过拖拽不同类型的节点(如事件、条件、动作等)到工作区,并通过连接线将这些节点连接起来,形成一个逻辑流程。

  2. 图形界面
    工具提供了一个直观的图形界面,使得开发者可以更容易地理解和管理复杂的逻辑结构。

  3. 底层代码生成
    在后台,这些工具会将可视化的节点和连接转换为底层的代码(如C++、C#或GDScript),并在运行时执行这些代码。

  4. 实时调试
    大多数可视化编程工具还提供了实时调试功能,允许开发者在运行时查看和修改节点的状态,以便快速找到和修复问题。

三、我要实现的RS蓝图系统

1、应用场景

低代码 / 定制产品化 / 插件化

2、核心功能

1、蓝图组件

它负责具体某个功能的实现以及实现方式、规范标准、回调、触发条件

2、蓝图编辑器

它负责将各个蓝图组件拼接起来构成一个完整的蓝图结构树,并保存起来

3、蓝图引擎

它负责解析蓝图结构树,并按顺序/触发条件调用蓝图组件,贯穿整个蓝图生命周期

4、可观测

蓝图生命周期的全局可视化

三、技术栈选型

1、前端

Vue3+Vite+TS

2、后端

Rust actix-web

3、数据库

Redis + PgSQL + MongoDB

4、监控

ELK

四、开发环境搭建

接下来我们搭建开发环境,并且实现最基本的蓝图节点组件。

1、操作系统 Deepin

Virtual Box 安装 Deepin 系统_virtualbox 安装deepin-CSDN博客文章浏览阅读220次,点赞10次,收藏3次。Virtual Box 安装 Deepin 系统_virtualbox 安装deepinhttps://blog.csdn.net/weixin_47560078/article/details/133959287?spm=1001.2014.3001.5502

2、搭建前端开发环境

安装 vs code,

安装 nodejs ,

# 安装 nodejs
sudo apt-get install nodejs

# 安装 npm
sudo apt-get install npm

# node 版本
node -v
v10.21.0


# n 模块是管理 nodejs 版本的
sudo npm install n -g

# 安装稳定版 nodejs
sudo n stable 

# nodejs 版本
node -v
v20.18.0

# npm 版本
npm -v
10.8.2

# 升级 npm
# sudo npm install -g npm 

# 安装编译工具包
sudo apt install build-essential

# 安装 cnpm
# sudo npm install -g cnpm --registry=http://registry.npmmirror.com

# 使用淘宝的镜像源
npm config set registry http://registry.npmmirror.com

3、搭建后端开发环境

安装 Rust,

# 官网 https://www.rust-lang.org/
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

修改 Rust 镜像源,

# $CARGO_HOME/.cargo/ 下创建 config.toml
$ touch config.toml
 
# 添加以下内容
 
[source.crates-io]
replace-with = 'ustc'
 
[source.ustc]
registry = "git://mirrors.ustc.edu.cn/crates.io-index"

4、搭建数据库环境

4.1、Redis

使用 apt 安装 redis,

sudo apt install redis-server
# redis-cli --version

redis 远程设置,

sudo vim /etc/redis/redis.conf 

# 注释掉绑定地址,让 Redis 可远程访问
# bind 127.0.0.1 ::1

# 取消注释 requirepass 启动密码认证,并设置访问密码
requirepass 0123456789

# 以守护进程运行Redis 
daemonize yes

重启 redis,

sudo systemctl restart redis-server

4.2、PgSQL

最终会跳转到指南页面,https://www.postgresql.org/download/linux/ubuntu/

一般的流程是引入软件包下载源,然后进行 apt 安装软件包,Ubuntu 通常已经包含了 postgresql 软件源,

sudo apt install -y postgresql-common
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
# 安装最新版本的 postgresql 
sudo apt install postgresql -y

查看运行状态跟版本,

sudo systemctl is-active postgresql
sudo systemctl is-enabled postgresql
sudo systemctl status postgresql
psql --version

安装过程会创建一个名为postgres的与默认postgres角色关联的用户账号,我们可以通过该账号来访问 PostgreSQL,

sudo -i -u postgres
(base) sam@sam-PC:~$ sudo -i -u postgres
postgres@sam-PC:~$ psql
psql (11.18 (Deepin 11.18-0+deb10u1))
输入 "help" 来获取帮助信息.

postgres=# help
您正在使用psql, 这是一种用于访问PostgreSQL的命令行界面
键入: \copyright 显示发行条款
       \h 显示 SQL 命令的说明
       \? 显示 pgsql 命令的说明
       \g 或者以分号(;)结尾以执行查询
       \q 退出
postgres=# \q
postgres@sam-PC:~$ exit
注销
(base) sam@sam-PC:~$ 

4.3、pgadmin4

pgsql 的官方可视化工具,这里使用 pip 安装,

创建文件夹,并且配置 web 登录的账号密码, 

$ sudo mkdir /var/lib/pgadmin
$ sudo mkdir /var/log/pgadmin
$ sudo chown $USER /var/lib/pgadmin
$ sudo chown $USER /var/log/pgadmin
# 创建 pgadmin4 python 环境
$ python3 -m venv pgadmin4
$ source pgadmin4/bin/activate
# 安装 pgadmin4
(pgadmin4) $ pip install pgadmin4
...
(pgadmin4) $ pgadmin4
NOTE: Configuring authentication for SERVER mode.

Enter the email address and password to use for the initial pgAdmin user account:

Email address: user@domain.com
Password: 
Retype password:
Starting pgAdmin 4. Please navigate to http://127.0.0.1:5050 in your browser.
 * Serving Flask app "pgadmin" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off

Conda 环境也可以,

# 配置路径
(myenv3.8) sam@sam-PC:~/anaconda3/envs/myenv3.8/lib/python3.8/site-packages/pgadmin4$ ls
babel.cfg          branding.py  config_distro.py  DEPENDENCIES  jest.config.js  migrations    pgacloud  pgAdmin4.py    __pycache__  sbom.json  version.py         webpack.shim.js
babel.config.json  commit_hash  config.py         docs          LICENSE         package.json  pgadmin   pgAdmin4.wsgi  README.md    setup.py   webpack.config.js  yarn.lock
(myenv3.8) sam@sam-PC:~/anaconda3/envs/myenv3.8/lib/python3.8/site-packages/pgadmin4$ 

访问 url , 输入刚刚在控制台设置的账号密码,

http://127.0.0.1:5050/browser/

配置 postgres 账号密码,然后创建一个新的 Servers 连接,

# psql
ALTER USER postgres WITH PASSWORD 'your_password';

配置 pgAdmin4 账号密码,登录,

开启语法提示:【配置-查询工具-自动完成】

4.4、MongoDB

安装,

# 下载地址
https://www.mongodb.com/try/download/community

tar -zxvf mongodb-linux-x86_64-ubuntu2004-8.0.4.tgz 

启动,

# 创建MongoDB要使用的目录和文件
sudo mkdir -p mongodb/data mongodb/log mongodb/conf
sudo touch mongodb/conf/mongodb.conf

修改配置文件内容

# sudo vim mongodb/conf/mongodb.conf

processManagement:
   fork: true
net:
   bindIp: localhost
   port: 27017
storage:
   dbPath: /home/sam/mongodb/data
systemLog:
   destination: file
   path: /home/sam/mongodb/log/mongod.log
   logAppend: true
storage:
   journal:
      enabled: true

使用配置文件启动

# 使用配置文件启动
bin/mongod -f /home/sam/mongodb/conf/mongodb.conf

# 关闭 MongoDB
# bin/mongod --shutdown --dbpath /home/sam/mongodb/data

报错,

./mongod: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by ./mongod)
./mongod: /lib/x86_64-linux-gnu/libpthread.so.0: version `GLIBC_2.30' not found (required by ./mongod)

看下当前系统存在哪些 GLIBC 版本,

strings /usr/lib64/libc.so.6 |grep GLIBC_
# 或者
strings /lib/x86_64-linux-gnu/libc.so.6 |grep GLIBC_

没有 29、30 的版本。

解决方案:

1、MongoDB 降版本

2、操作系统升版本

3、升级 glibc (物理机慎操作)

https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu1804-6.0.19.tgz

再次启动 MongoDB,成功。

# sudo bin/mongod -f /home/sam/mongodb/conf/mongodb.conf

about to fork child process, waiting until server is ready for connections.
forked process: 4967
child process started successfully, parent exiting

五、前端框架搭建

1、整合 Vue + Vite + ElementUI

# 创建 vite vue
cnpm create vite@latest

# element-plus 国内镜像 https://element-plus.gitee.io/zh-CN/
# 安装 element-plus
cnpm install element-plus --save

按需引入 element plus,

cnpm install -D unplugin-vue-components unplugin-auto-import

在 main.ts 引入 element-plus 和样式,

// src\main.ts
import { createApp } from 'vue'
//import './style.css'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
 
createApp(App).use(ElementPlus).mount('#app')

配置 vite,

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
 
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
})

2、安装依赖

axios + vue-draggable

cnpm install axios

cnpm install vuedraggable@next

cnpm install sass-embedded

3、创建基本组件

在src/components目录下创建两个文件:Node.vue和Canvas.vue。

// Node.vue
<template>
  <div class="node" :style="{ top: node.y + 'px', left: node.x + 'px' }">
    {{ node.name }}
  </div>
</template>

<script lang="ts" setup>
import { defineProps } from 'vue'

interface Node {
  x: number;
  y: number;
  name: string;
}

const props = defineProps<{ node: Node }>()
</script>

<style scoped>
.node {
  position: absolute;
  width: 100px;
  height: 50px;
  background-color: lightblue;
  border: 1px solid #000;
  text-align: center;
  line-height: 50px;
  cursor: move;
}
</style>
// Canvas.vue
<template>
    <div class="canvas">
        <draggable
            v-model:list="state.nodes"
            :disabled="!state.enabled"
            item-key="id"
            class="w-100"
            ghost-class="ghost"
            chosen-class="chosen"
            @start="state.dragging = true"
            @end="onDragEnd"
            animation="300"
        >
            <template #item="{ element }">
                <Node :node="element" />
            </template>
        </draggable>
    </div>
</template>

<script lang="ts" setup>
import { reactive, ref } from 'vue'
import draggable from 'vuedraggable'
import Node from './Node.vue'

interface Node {
    id: number;
    name: string;
    x: number;
    y: number;
}

const state = reactive({
    enabled: true,
    nodes: [
        { id: 1, name: 'Start', x: 50, y: 50 },
        { id: 2, name: 'Process', x: 200, y: 50 }
    ],
    dragging: false
})

function onDragEnd(event: any) {
    state.dragging = false;
    // Update node positions after drag
}

</script>

<style scoped lang="scss">
.canvas {
    width: 100%;
    height: 100vh;
    position: relative;
    background-color: #f0f0f0;
}
.ghost {
    opacity: 0.5;
    border: 1px solid #18a058;
}
.chosen {
    border: 1px solid #18a058;
}
.item {
    width: 100%;
    &:hover {
        background-color: #f0f0f0;
    }
}
.not-draggable {
    cursor: no-drop;
}
</style>

更新App.vue,

// App.vue
<script setup lang="ts">
import Canvas from './components/Canvas.vue'

</script>

<template>
<Canvas/>
</template>

<style scoped>
</style>

运行效果,

修改 Canvas.vue,从后端获取数据,

// ...

import axios from 'axios'

// ...

onMounted(() => {
    axios.get('http://localhost:8080/nodes')
        .then(response => {
            state.nodes = response.data;
        })
        .catch(error => {
            console.error(error);
        });
})

// ...

六、后端框架搭建

1、基础框架

首先,创建一个新的二进制 Cargo 项目,并切换到新目录:

cargo new backend
cd backend

通过向 Cargo.toml 文件添加以下内容,将 actix-web 添加为项目的依赖项。

[dependencies]
actix-web = "4"

请求 handler 使用异步函数,接受零个或多个参数。

use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};

#[get("/")]
async fn hello() -> impl Responder {
    HttpResponse::Ok().body("Hello world!")
}

#[post("/echo")]
async fn echo(req_body: String) -> impl Responder {
    HttpResponse::Ok().body(req_body)
}

async fn manual_hello() -> impl Responder {
    HttpResponse::Ok().body("Hey there!")
}

接下来,创建 App 实例并注册请求 handler。

  • 对于使用了路由宏的 handler,使用 App::service 方法注册路由;
  • 对不使用路由宏而注册自定义路由的情况,使用 App::route 方法。

最后,使用 HttpServer 启动应用程序。

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(hello)
            .service(echo)
            .route("/hey", web::get().to(manual_hello))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

编译并运行程序

cargo run 

访问 http://localhost:8080/

2、序列化 Node 节点

 修改  Cargo.toml,新增序列化依赖,对应序列化 Node 节点,

serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
use serde::Serialize;

#[derive(Serialize)]
struct Node {
    id: u32,
    name: String,
    x: i32,
    y: i32,
}

#[get("/nodes")]
async fn get_nodes() -> impl Responder {
    let nodes = vec![
        Node { id: 1, name: "Start".to_string(), x: 50, y: 50 },
        Node { id: 2, name: "Process".to_string(), x: 200, y: 50 },
    ];
    
    HttpResponse::Ok().json(nodes)
}


#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .service(get_nodes)
    })
    .bind("0.0.0.0:8080")?
    .run()
    .await
}

3、跨域请求

接口测试成功,但是还有一个跨域问题,

在 actix-web 里, 我们需要配合 actix_cors 来处理关于跨域请求的配置,

[dependencies]
actix-cors = "0.7.0"
// main.rs
use actix_web::{get, http, post, web, App, HttpResponse, HttpServer, Responder};
use serde::Serialize;
use actix_cors::Cors;

#[derive(Serialize)]
struct Node {
    id: u32,
    name: String,
    x: i32,
    y: i32,
}

#[get("/nodes")]
async fn get_nodes() -> impl Responder {
    let nodes = vec![
        Node { id: 1, name: "Start".to_string(), x: 50, y: 50 },
        Node { id: 2, name: "Process".to_string(), x: 200, y: 50 },
    ];
    
    HttpResponse::Ok().json(nodes)
}


#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        let cors = Cors::default()
        .allowed_origin("http://localhost:5173")
        // .allowed_origin_fn(|origin, _req_head| {
        //     origin.as_bytes().ends_with(b".rust-lang.org")
        // })
        .allowed_methods(vec!["GET", "POST"])
        .allowed_headers(vec![http::header::AUTHORIZATION, http::header::ACCEPT])
        .allowed_header(http::header::CONTENT_TYPE)
        .max_age(3600);

        App::new()
        .wrap(cors)
        .service(get_nodes)
    })
    .bind("0.0.0.0:8080")?
    .run()
    .await
}

效果,

参考资料

介绍 - actix-web 中文文档 - Rust-Web 开发指南

actix_web - Rust

actix_cors - Rust

https://dev.epicgames.com/documentation/zh-cn/unreal-engine/overview-of-blueprints-visual-scripting-in-unreal-engine

PostgreSQL: The world's most advanced open source database

pgAdmin - PostgreSQL Tools

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++ 类和对象 基础篇】—— 抽象思维的巅峰舞者,演绎代码的深邃华尔兹

C学习笔记&#xff1a; C 进阶之路__Zwy的博客-CSDN博客 各位于晏&#xff0c;亦菲们&#xff0c;请点赞关注&#xff01; 我的个人主页&#xff1a; _Zwy-CSDN博客 目录 1、类 1.1、类的定义 1.2、访问限定符 1.2.1、public 1.2.2、private 1.2.3、protected 1.3、…

(高可用版本)Kubeadm+Containerd+keepalived部署高可用k8s(v1.28.2)集群

KubeadmContainerdkeepalived部署高可用k8s(v1.28.2)集群 一.环境准备&#xff0c;二.容器运行时Containerd安装请参照前文。KubeadmContainerd部署k8s(v1.28.2)集群&#xff08;非高可用版&#xff09;-CSDN博客 文章目录 KubeadmContainerdkeepalived部署高可用k8s(v1.28.2)集…

联合目标检测与图像分类提升数据不平衡场景下的准确率

联合目标检测与图像分类提升数据不平衡场景下的准确率 在一些数据不平衡的场景下&#xff0c;使用单一的目标检测模型很难达到99%的准确率。为了优化这一问题&#xff0c;适当将其拆解为目标检测模型和图像分类模型的组合&#xff0c;可以更有效地控制最终效果&#xff0c;尤其…

C++之红黑树模拟实现

目录 红黑树的概念 红黑树的性质 红黑树的查找效率 红黑树的实现 红黑树的定义 红黑树节点的插入 红黑树的平衡调整 判断红黑树是否平衡 红黑树整体代码 测试代码 上期我们学习了AVL树的模拟实现&#xff0c;在此基础上&#xff0c;我们本期将学习另一个数据结构-…

机器学习常用术语

目录 概要 机器学习常用术语 1、模型 2、数据集 3、样本与特征 4、向量 5、矩阵 6、假设函数与损失函数 7、拟合、过拟合与欠拟合 8、激活函数(Activation Function) 9、反向传播(Backpropagation) 10、基线(Baseline) 11、批量(Batch) 12、批量大小(Batch Size)…

nest 学习3

学习小册(nest通关秘籍) 邮箱验证码登陆 流程图&#xff1a; 邮箱作为key&#xff0c;生成随机验证码&#xff0c;然后放到redis中。调用邮箱api发送邮箱。 前端获取到code后&#xff0c;将验证码输入传给后端&#xff0c;后端根据邮箱取出redis数据&#xff0c;比对验证码&…

原点安全再次入选信通院 2024 大数据“星河”案例

近日&#xff0c;中国信息通信研究院和中国通信标准化协会大数据技术标准推进委员会&#xff08;CCSA TC601&#xff09;共同组织开展的 2024 大数据“星河&#xff08;Galaxy&#xff09;”案例征集活动结果正式公布。由工银瑞信基金管理有限公司、北京原点数安科技有限公司联…

RabbitMQ 的7种工作模式

RabbitMQ 共提供了7种⼯作模式,进⾏消息传递,. 官⽅⽂档:RabbitMQ Tutorials | RabbitMQ 1.Simple(简单模式) P:⽣产者,也就是要发送消息的程序 C:消费者,消息的接收者 Queue:消息队列,图中⻩⾊背景部分.类似⼀个邮箱,可以缓存消息;⽣产者向其中投递消息,消费者从其中取出消息…

Restaurants WebAPI(四)——Identity

文章目录 项目地址一、Authentication&#xff08;身份认证&#xff09;1.1 配置环境(解决类库包无法引用)1.2 使用Authentication控制Controller的访问1.3 获取User的Context1.3.1 在Application下创建User文件夹1. 创建User.cs record类封装角色信息2. 创建UserContext.cs提供…

010 Qt_输入类控件(LineEdit、TextEdit、ComboBox、SpinBox、DateTimeEdit、Dial、Slider)

文章目录 前言一、QLineEdit1.简介2.常见属性及说明3.重要信号及说明4.示例一&#xff1a;用户登录界面5.示例二&#xff1a;验证两次输入的密码是否一致显示密码 二、TextEdit1.简介2.常见属性及说明3.重要信号及说明4.示例一&#xff1a;获取多行输入框的内容5.示例二&#x…

Vue3:uv-upload图片上传

效果图&#xff1a; 参考文档&#xff1a; Upload 上传 | 我的资料管理-uv-ui 是全面兼容vue32、nvue、app、h5、小程序等多端的uni-app生态框架 (uvui.cn) 代码&#xff1a; <view class"greenBtn_zw2" click"handleAddGroup">添加班级群</vie…

通过Docker Compose来实现项目可以指定读取不同环境的yml包

通过Docker Compose来实现项目可以指定读取不同环境的yml包 1. 配置文件2. 启动命令 切换不同环境注意挂载的文件权限要777 1. 配置文件 version: 3.8 services:docker-test:image: openjdk:8-jdk-alpineports:- "${APP_PORT}:${CONTAINER_PORT}"volumes:- "${J…

华为实训课笔记 2024 1223-1224

华为实训 12/2312/24 12/23 [Huawei]stp enable --开启STP display stp brief --查询STP MSTID Port Role STP State Protection 实例ID 端口 端口角色 端口状态 是否开启保护[Huawei]display stp vlan xxxx --查询制定vlan的生成树计算结…

GitCode 光引计划投稿 | GoIoT:开源分布式物联网开发平台

GoIoT 是基于Gin 的开源分布式物联网&#xff08;IoT&#xff09;开发平台&#xff0c;用于快速开发&#xff0c;部署物联设备接入项目&#xff0c;是一套涵盖数据生产、数据使用和数据展示的解决方案。 GoIoT 开发平台&#xff0c;它是一个企业级物联网平台解决方案&#xff…

EasyGBS国标GB28181公网平台P2P远程访问故障诊断:云端服务端排查指南

随着信息技术的飞速发展&#xff0c;视频监控领域正经历从传统安防向智能化、网络化安防的深刻转变。EasyGBS平台&#xff0c;作为基于国标GB28181协议的视频流媒体平台&#xff0c;为用户提供了强大的视频监控直播功能。然而&#xff0c;在实际应用中&#xff0c;P2P远程访问可…

Vnlhun靶场Log4j2漏洞

相关概念 log4j2是Apache的⼀个java日志框架&#xff0c;我们借助它进行日志相关操作管理&#xff0c;然而在2021年末log4j2爆出了远程代码执行漏洞&#xff0c;属于严重等级的漏洞 漏洞原理 简单说就是当你使⽤log4j2中提供的⽅法去输出⽇志信息时&#xff0c;⽐如说最常⻅…

千兆网中的gmii与rgmii

物理链路上是千兆网。1 Gbps1000 Mb/s1000/8 MB/s125 MB/s&#xff0c;这是和你的测试设备相连的1 Gbps物理带宽下的极速。关键点是1 B&#xff08;byte&#xff09;8 b&#xff08;bit&#xff09;。实际下载速度还取决于下载源的限制、出口的物理链路和运营商的限制。

2024-12-24 NO1. XR Interaction ToolKit 环境配置

文章目录 1 软件配置2 安装 XRToolKit3 配置 OpenXR4 安装示例场景5 运行测试 1 软件配置 Unity 版本&#xff1a;Unity6000.0.26 ​ 2 安装 XRToolKit 创建新项目&#xff08;URP 3D&#xff09;&#xff0c;点击进入 Asset Store。 进入“Unity Registry”页签&#xff0…

重温设计模式--外观模式

文章目录 外观模式&#xff08;Facade Pattern&#xff09;概述定义 外观模式UML图作用 外观模式的结构C 代码示例1C代码示例2总结 外观模式&#xff08;Facade Pattern&#xff09;概述 定义 外观模式是一种结构型设计模式&#xff0c;它为子系统中的一组接口提供了一个统一…

【恶意软件检测】一种基于API语义提取的Android恶意软件检测方法(期刊等级:CCF-B、Q2)

一种基于API语义提取的Android恶意软件检测方法 A novel Android malware detection method with API semantics extraction 摘要 由于Android框架和恶意软件的持续演变&#xff0c;使用过时应用程序训练的传统恶意软件检测方法在有效识别复杂演化的恶意软件方面已显不足。为…