Unity-Mirror网络框架-从入门到精通之Room示例
文章目录
- 前言
- Room示例
- 场景设置
- NetworkRoomManager
- Spawner
- Reward
- RoomPlayer
- GamePlayer
- 最后
前言
在现代游戏开发中,网络功能日益成为提升游戏体验的关键组成部分。Mirror是一个用于Unity的开源网络框架,专为多人游戏开发设计。它使得开发者能够轻松实现网络连接、数据同步和游戏状态管理。本文将深入介绍Mirror的基本概念、如何与其他网络框架进行比较,以及如何从零开始创建一个使用Mirror的简单网络项目。
Room示例
今天我们来讲一下MirrorNetworking网络框架示例中比较有代表意义的Room示例。
它主要讲了如何用Mirror来实现一个房间系统,
为什么要有房间呢?
只要你玩过游戏,你一定只要,当你点击开始游戏后,不是直接进入游戏对战,而是会有一个游戏模式选择,游戏匹配,创建房间,加入房间,好友组队等,然后再进入游戏。
如王者荣耀的匹配房间:
再看示例的房间,如下所示
这是一个房间信息,列表中是房间内的玩家信息
玩家的准备状态
房间匹配
如果所有玩家都准备的情况下,Host端或者Server端,会显示 开始游戏 按钮
点击 开始游戏 按钮,会进入游戏场景
游戏场景
游戏场景中会随机生成一些小道具在场景中,玩家可以通过WASD等按键,操作自己的角色区拾取道具。
一个简单而又功能完善的 带房间的小游戏。
场景设置
我们打开Scenes文件夹,看到这个示例中,共有3个场景
MirrorGameOffLine:离线场景,作为示例的启动场景,连接或者启动服务器后跳转到OnLine场景
MirrorGameOnLine:房间场景,玩家上线后,进入房间,此时属于房间阶段,可以做一些匹配或者选择模式等逻辑。
MirrorGameGame:游戏场景,当所有玩家准备后,服务器点击StartGame,进入Game场景,开始小游戏。
OffLine场景
OffLine场景中,只有一个NetworkRoomManager游戏对象,作为全局的网络管理器。挂在了组件
NetworkRoomManagerExt,继承自NetworkRoomManager。
而NetworkRoomManager又继承自NetworkManager。
所以实际上NetworkManager可以做简单的直连网络小游戏,也可以通过扩展,添加房间,匹配等逻辑,实现更为复杂的带大厅、房间匹配等复杂逻辑的游戏的。
OnLine场景
OnLine场景其实是一个空场景,因为Room示例,使用的是GUI来做的,所以这里直接省略了UI逻辑。
其实就是这个房间信息页面,不过所有的显示逻辑都在RoomPlayer里面写了。
Game场景
这个Game场景,也就设置了一个游戏的场景,一些出生点。
当玩家进入GameScene后,有NetworkRoomManagerExt来处理GamePlayer的创建。
public virtual void OnServerAddPlayer(NetworkConnectionToClient conn){Transform startPos = GetStartPosition();GameObject player = startPos != null? Instantiate(playerPrefab, startPos.position, startPos.rotation): Instantiate(playerPrefab);// instantiating a "Player" prefab gives it the name "Player(clone)"// => appending the connectionId is WAY more useful for debugging!player.name = $"{playerPrefab.name} [connId={conn.connectionId}]";NetworkServer.AddPlayerForConnection(conn, player);}
其他的游戏逻辑,还是在GamePlayer上面。保罗玩家的运动控制和运动同步,颜色变化等等。
而奖励金币的创建逻辑在Spawner上面。
这里有一个回收和延迟1秒,再创建的逻辑。
[ServerCallback]internal static void SpawnReward(){Vector3 spawnPosition = new Vector3(Random.Range(-19, 20), 1, Random.Range(-19, 20));NetworkServer.Spawn(Get(spawnPosition, Quaternion.identity));}[ServerCallback]internal static async void RecycleReward(GameObject reward){NetworkServer.UnSpawn(reward);Return(reward);await DelayedSpawn();}static async Task DelayedSpawn(){await Task.Delay(new System.TimeSpan(0, 0, 1));SpawnReward();}
NetworkRoomManager
NetworkRoomManager的话,我来把它简化下,给大家说一下它到底是个什么
namespace Mirror
{[AddComponentMenu("Network/Network Room Manager")]public class NetworkRoomManager : NetworkManager{public int minPlayers = 1;public NetworkRoomPlayer roomPlayerPrefab;public string RoomScene;public string GameplayScene;//房间中的玩家连接列表public HashSet<PendingPlayer> pendingPlayers = new HashSet<PendingPlayer>();//public HashSet<NetworkRoomPlayer> roomSlots = new HashSet<NetworkRoomPlayer>();//internal void CallOnClientEnterRoom()internal void CallOnClientExitRoom()public void CheckReadyToBegin()#region 客户端回调public override void OnStartClient()public override void OnClientConnect()public override void OnClientDisconnect()public override void OnStopClient()public override void OnClientSceneChanged()#endregion#region 房间虚函数,server端public virtual void OnRoomStartHost() {}public virtual void OnRoomStopHost() {}public virtual void OnRoomStartServer() {}public virtual void OnRoomStopServer() {}public virtual void OnRoomServerConnect(NetworkConnectionToClient conn) {}public virtual void OnRoomServerDisconnect(NetworkConnectionToClient conn) {}public virtual void OnRoomServerSceneChanged(string sceneName) {}public virtual void ReadyStatusChanged(){}public virtual void OnRoomServerPlayersReady(){}public virtual void OnRoomServerPlayersNotReady() {}#endregion#region 房间虚函数client端public virtual void OnRoomClientEnter() {}public virtual void OnRoomClientExit() {}public virtual void OnRoomClientConnect() {}public virtual void OnRoomClientDisconnect() {}public virtual void OnRoomStartClient() {}public virtual void OnRoomStopClient() {}public virtual void OnRoomClientSceneChanged() {}#endregion}
}
首先 它又两个HashSet,分别是pendingPlayers和roomSlots,都是存储player引用的,一个是connect引用,一个是roomPlayer组件引用。相当于帮我们封装了一个房间,里面又玩家信息。
然后 我们看到下面有一堆和room相关的虚函数,也就是说在客户端连接服务器后,NetworkRoomManager强行给我们加了一个进入游戏Game的中间层,并新加了一些生命周期的函数,比如OnRoomStartServer,OnRoomStartClient等等。
这些生命周期和父类中的OnStartServer,OnStartClient,其实是一回事。
如下所示:
OnRoomStartClient只不是在OnStartClient时判断了一下roomPlayerPrefab的判空。
其他虚函数也基本类似,就是多了一些判断和修饰,本质上还是NetworkManager。
public override void OnStartClient(){if (roomPlayerPrefab == null || roomPlayerPrefab.gameObject == null)Debug.LogError("NetworkRoomManager no RoomPlayer prefab is registered. Please add a RoomPlayer prefab.");elseNetworkClient.RegisterPrefab(roomPlayerPrefab.gameObject);if (playerPrefab == null)Debug.LogError("NetworkRoomManager no GamePlayer prefab is registered. Please add a GamePlayer prefab.");OnRoomStartClient();}
所以当我们用到这个NetworkRoomManager做房间管理时,我们在使用生命周期虚函数,就可以在函数中间加上Room,改成OnRoomXXX函数即可。
Spawner
在NetworkRoomManagerExt中的OnRoomServerSceneChange中,有一个判断,如果是Game场景,则开始生成金币道具,
客户端的OnRoomClientSceneChange是客户端的场景切换回调,如果是Game场景,则初始化金币对象池。这样就避免了金币道具的频繁销毁和创建,而是从对象池中获取
public class NetworkRoomManagerExt : NetworkRoomManager{[Header("Spawner Setup")][Tooltip("Reward Prefab for the Spawner")]public GameObject rewardPrefab;public byte poolSize = 10;public override void OnRoomServerSceneChanged(string sceneName){// spawn the initial batch of Rewardsif (sceneName == GameplayScene){Spawner.InitializePool(rewardPrefab, poolSize);Spawner.InitialSpawn();}elseSpawner.ClearPool();}public override void OnRoomClientSceneChanged(){if (NetworkServer.active) return;if (networkSceneName == GameplayScene)Spawner.InitializePool(rewardPrefab, poolSize);elseSpawner.ClearPool();}}
Spawner的对象池机制
这个NetworkClient.RegisterPrefab机制,是一套创建网络对象的本地创建重载,方便使用对象池,来处理一些大量频繁创建销毁的物体。
internal static void InitializePool(GameObject poolPrefab, byte count){prefab = poolPrefab;poolSize = count;NetworkClient.RegisterPrefab(prefab, SpawnHandler, UnspawnHandler);pool = new Pool<GameObject>(CreateNew, poolSize);}
Reward
金币奖励道具,着重说一下OnTriggerEnter函数,它已经不是Unity声明周期的OnTriggerEnter函数了,它是经过了网络组件同步的OnTriigerEnter,有服务器来调用,因为客户端调用没有什么意义。
ServerCallback:代表了这个函数只在服务器运行。
[ServerCallback]void OnTriggerEnter(Collider other){if (!gameObject.activeSelf) return;if (!other.CompareTag("Player")) return;if (!available)return;available = false;uint points = (uint)((randomColor.color.r + randomColor.color.g + randomColor.color.b) / 3);//加分other.GetComponent<PlayerScore>().score += points;//回收对象Spawner.RecycleReward(gameObject);}
RoomPlayer
RoomPlayer是房间中的玩家,它的显示,完全是使用GUI来做的,内部也没有什么逻辑,只有一个准备逻辑,当玩家调用准备函数式,会发送给服务器
[Command]命令,代表客户端调用服务器函数,客户端点了准备按钮后,服务器刷新整体显示。
[Command]public void CmdChangeReadyState(bool readyState){readyToBegin = readyState;NetworkRoomManager room = NetworkManager.singleton as NetworkRoomManager;if (room != null){room.ReadyStatusChanged();}}
GamePlayer
在Room示例中,GamePlayer有两个实现,分别是GamePlayerReliable和GamePlayerUnreliable
他们有什么区别呢?
我们注意到两个预制体的NetworkTransform组件不一样
它们的主要区别如下:
-
1.可靠性:
GamePlayerReliable: 这个预制体通常用于需要保证数据传送可靠性的情况。例如,玩家的状态更新、输入指令等关键数据需要确保每个数据包都能成功到达目标客户端,因此适合使用可靠的网络传输方式。这意味着在传输过程中,即使数据包丢失,网络会重发该数据包以确保数据的完整性
GamePlayerUnreliable: 该预制体则使用不可靠的传输方式,适合对实时性要求更高但可以容忍丢包的情境。例如,物体的位置信息更新可以采用不可靠的方式,因为在快节奏的游戏中,丢失一两个包可能不会对游戏体验造成显著影响。这种方式减少了网络带宽的占用,但对数据传输的完整性没有保证 -
2.性能与延迟:
GamePlayerReliable: 因需要确认每个数据包的送达,导致在网络不佳的情况下可能出现延迟,影响游戏体验。尤其当网络拥挤时,重复的数据包和确认消息可能会导致更多的延迟
GamePlayerUnreliable: 更加轻量,适合快速更新和更少的延迟。在高速新的游戏场景中,使用不可靠的传输方式允许更快速的状态更新,使得玩家能够获得更顺畅的体验,尽管会有数据丢失的风险 -
3.使用场景:
GamePlayerReliable: 适用于需要确保操作准确无误的场景,如玩家首次连接、系统配置、重要游戏状态等需要准确传输的数据
GamePlayerUnreliable: 更适合于实时的游戏元素交互,如角色的移动和技能释放等,这些更新频繁且不一定需要每次都保证准确传递,允许使用更新丢失而不影响整体游戏进行的情况
我们抛开它们的区别不谈的话,其实GamePlayer就是游戏场景中的,第一人称玩家,他可以控制任务移动,去吃金币,
这里主要说一下NetworkTransform组件,它是用于Unity的游戏对象的Transform的同步的,是最常用的一个同步组件了,因为我们做多人游戏,最重要的是物体的位置,旋转同步。而NetworkTransform就很好的处理的物体的运动平滑和同步。
最后
最后运行起来后呢,就是如下图所示的一个非常简单的吃金币的小游戏了
我们可以通过这个示例,怎么扩展我们的多人游戏呢?
1.是否可以把GUI修改成UGUI呢?(必须可以,而且是必须要做的)
2.是否可以给RoomPlayer扩展一些功能?比如这是名字,选择身份,选择武器等等?
3.是否可以扩展一下GamePlayer,把这个吃金币小游戏,扩展成一个第一人称射击小游戏呢?
如果你想挑战自己,不妨照着做下试试,会有意想不到的收获哦
希望这篇文章对你有所帮助
如果有问题欢迎留言讨论。
相关文章:
Unity-Mirror网络框架-从入门到精通之Room示例
文章目录 前言Room示例场景设置NetworkRoomManagerSpawnerRewardRoomPlayerGamePlayer 最后 前言 在现代游戏开发中,网络功能日益成为提升游戏体验的关键组成部分。Mirror是一个用于Unity的开源网络框架,专为多人游戏开发设计。它使得开发者能够轻松实现…...
httpslocalhostindex 配置的nginx,一刷新就报404了
当你的Nginx配置导致页面刷新时报404错误时,通常是由于以下几个原因造成的: 静态文件路径配置错误:Nginx没有正确地指向静态文件的目录。前端路由问题:如果是SPA(单页应用),刷新页面时Nginx没有…...
Java重要面试名词整理(十九):Seata
文章目录 分布式事务概述实现思路:两阶段提交协议(2PC) SeataSeata的三大角色Seata的生命周期Seata解决方案 AT模式一阶段二阶段 XA模式TCC模式如何处理空回滚如何处理幂等如何处理悬挂 SAGA模式四种模式对比 分布式事务概述 在微服务架构中,完成某一个…...
OpenCV和PyQt的应用
1.创建一个 PyQt 应用程序,该应用程序能够: 使用 OpenCV 加载一张图像。在 PyQt 的窗口中显示这张图像。提供四个按钮(QPushButton): 一个用于将图像转换为灰度图一个用于将图像恢复为原始彩色图一个用于将图像进行翻…...
【Linux】进程间通信(一)
目录 一、进程间通信1.1 进程间通信目的1.2 理解进程间通信1.3 进程间通信发展1.4 进程间通信分类 二、管道2.1 什么是管道2.2 管道的原理2.3 匿名管道2.3.1 pipe函数2.3.2 匿名管道的实现2.3.3 匿名管道小结2.3.3.1 匿名管道的四种情况2.3.3.2 匿名管道的五种特性 2.3.4 匿名管…...
Fama MacBeth两步法与多因子模型的回归检验
Fama MacBeth两步法与多因子模型的回归检验 – 潘登同学的因子投资笔记 本文观点来自最近学习的石川老师《因子投资:方法与实践》一书 文章目录 Fama MacBeth两步法与多因子模型的回归检验 -- 潘登同学的因子投资笔记 多因子回归检验时序回归检验截面回归检验Fama–…...
Postman[4] 环境设置
作用:不同的环境可以定义不同的参数,在运行请求时可以根据自己的需求选择需要的环境 1.创建Environment 步骤: Environment-> ->命名->添加环境变量 2.使用Environment 步骤:Collection- >右上角选择需要的环境...
【paddle】初次尝试
张量 张量是 paddlepaddle, torch, tensorflow 等 python 主流机器学习包中唯一通货变量,因此应当了解其基本的功能。 张量 paddle.Tensor 与 numpy.array 的转化 import paddle as paddle import matplotlib.pyplot as plt apaddle.to_t…...
开源架构中的数据库选择优化版
上一篇文章推荐: 开源架构学习指南:文档与资源的智慧锦囊(New) 我管理的社区推荐:【青云交社区】和【架构师社区】 推荐技术圈福利社群:点击快速加入 开源架构中的数据库选择优化版 一、引言二、关系型开源…...
Echarts+vue电商平台数据可视化——webSocket改造项目
websocket的基本使用,用于测试前端能否正常获取到后台数据 后台代码编写: const path require("path"); const fileUtils require("../utils/file_utils"); const WebSocket require("ws"); // 创建WebSocket服务端的…...
【网络安全实验室】SQL注入实战详情
如果额头终将刻上皱纹,你只能做到,不让皱纹刻在你的心上 1.最简单的SQL注入 查看源代码,登录名为admin 最简单的SQL注入,登录名写入一个常规的注入语句: 密码随便填,验证码填正确的,点击登录…...
【信息系统项目管理师】第14章:项目沟通管理过程详解
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 一、规划沟通管理1、输入2、工具与技术3、输出二、管理沟通1、输入2、工具与技术3、输出三、监督沟通1、输入2、工具与技术3、输出一、规划沟通管理 定义:规划沟通管理是基于每个干系人或干系人群体的信息需求…...
YOLOv5部署到web端(flask+js简单易懂)
文章目录 前言最终实现效果图后端实现 主界面检测函数检测结果显示 前端实现 主界面(index.html)显示图片界面 总结 前言 最近,老板让写一个程序把yolov5检测模型部署到web端,在网页直接进行目标检测。经过1个星期的努力,终于实…...
什么是自治系统和非自治系统
自治系统 自治系统的特征是其状态方程不依赖于时间。举个简单的例子,考虑一阶常微分方程: d x d t − x \frac{dx}{dt} -x dtdx−x 这是一个经典的指数衰减过程,其中状态 (x) 随时间 (t) 衰减。这个系统是自治的,因为它的演…...
使用 CSS 的 `::selection` 伪元素来改变 HTML 文本选中时的背景颜色
定义 ::selection 伪元素: 在你的 CSS 文件中,添加 ::selection 伪元素,并设置 background-color 属性来改变选中文本的背景颜色。 示例代码: ::selection {background-color: yellow; /* 你可以根据需要更改颜色 */color: black…...
从0入门自主空中机器人-3-【环境与常用软件安装】
关于本课程: 本次课程是一套面向对自主空中机器人感兴趣的学生、爱好者、相关从业人员的免费课程,包含了从硬件组装、机载电脑环境设置、代码部署、实机实验等全套详细流程,带你从0开始,组装属于自己的自主无人机,并让…...
jmeter分布式启动
https://www.cnblogs.com/qtclm/p/11082081.html 1、代理机:输入“ipconfig”,找到IP地址,在Jmeter/bin/jmeter.properties设置remote host 启动jmeter server 1、控制机:输入“ipconfig”,找到IP地址,在J…...
【Linux】HTTP cookie与session
在登录B站时,有登录和未登录两种状态, 问题:B站是如何认识我这个登录用户的?问题:HTTP是无状态、无连接的,怎么能够记住我? HTTP协议是无状态、无连接的。比如客户端(浏览器&#…...
20. 【.NET 8 实战--孢子记账--从单体到微服务】--简易权限--补充--自动添加接口地址
在同学学习过程,部分同学向我反馈说每次新增接口都要在接口表里手动添加一条接口很麻烦,因此我把项目代码做了一个改动,使我们不需要手动添加,每次项目运行起来后就会自动把新的接口地址添加进去。 一、实现 首先,我…...
[Linux] 服务器CPU信息
(1)查看CPU信息(型号) cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c输出:可以看到有128个虚拟CPU核心,型号是后面一串 128 Intel(R) Xeon(R) Platinum 8336C CPU 2.30GHz(2&…...
java_使用阿里云oss服务存储图片
什么情况下可以使用阿里云oss服务存储图片? 对图片的访问速度有高要求时使用,方便用户快速的(比如在网页页面中)访问到图像 参考:41 尚上优选项目-平台管理端-商品信息管理模块-阿里云OSS介绍_哔哩哔哩_bilibili 1.…...
Dali 1.1.4 | 解锁版AI图像生成器,无限生成
Dali是一款先进的AI图像生成器应用程序,能够根据您的描述生成不同风格的独特图像。它不仅限于生成艺术作品,还可以创建创新的纹身设计、独一无二的标志以及超写实照片。该软件使用尖端技术,将想象力转化为现实,提供迷人的数字艺术…...
快手视频不让下载怎么保存到相册
快手,作为国内领先的短视频平台之一,吸引了无数用户发布创意视频、分享生活点滴。随着短视频版权保护和用户隐私问题的日益严重,越来越多的视频内容在平台内都采取了“不让下载”的限制。面对这一情况,很多用户都希望能够保存自己…...
Linux环境下CUDA与对应版本CuDNN的安装指南
转载:Linux环境下CUDA与对应版本CuDNN的安装指南-百度开发者中心...
mybatisPlus打印sql配置
MyBatis-Plus 提供了方便的配置方式来打印 SQL 查询语句,以便进行调试和性能分析。可以通过配置 log 来输出 SQL 语句以及执行的参数。 方法 1:通过 application.properties 或 application.yml 配置打印 SQL 可以通过配置 application.properties 或 a…...
InstructGPT:基于人类反馈训练语言模型遵从指令的能力
大家读完觉得有意义记得关注和点赞!!! 大模型进化树,可以看到 InstructGPT 所处的年代和位置。来自 大语言模型(LLM)综述与实用指南(Amazon,2023) 目录 摘要 1 引言 …...
曾仕强解读《易经》
曾仕强对《易经》的解读内容丰富、深入浅出,以下是一些主要方面: 讲解《易经》基本原理 - 阴阳之道:曾仕强将阴阳比作白天与黑夜、男人与女人等,指出阴阳看似对立,实则相辅相成,强调为人处世要把握阴阳…...
http报头解析
http报文 http报文主要有两类是常见的,第一类是请求报文,第二类是响应报文,每个报头除了第一行,都是采用键值对进行传输数据,请求报文的第一行主要包括http方法(GET,PUT, POST&#…...
什么是Sight Words(信号词)
🧡什么是Sight Words(信号词) 简单来说,Sight Words就是我们在日常英语中常用的一些基本词汇。可以把它想象成是学练英语的“基础词汇”,这些词在各种考试中经常出现,也是在生活中必不可少的。 …...
tiny RISCV项目学习
参考视频:第1期 开发环境准备 —— RISC-V囫囵吞枣式学习_哔哩哔哩_bilibili 项目地址:tinyriscv: 一个从零开始写的极简、非常易懂的RISC-V处理器核。...
LeetCode 力扣 热题 100道(二十七)除自身以外数组的乘积(C++)
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂…...
Kotlin在医疗大健康域的应用实例探究与编程剖析(上)
一、引言 1.1 研究背景与意义 在当今数字化时代,医疗行业正经历着深刻的变革。随着信息技术的飞速发展,尤其是人工智能、大数据、物联网等新兴技术的广泛应用,医疗行业数字化转型已成为必然趋势。这种转型旨在提升医疗服务的效率和质量,优化医疗资源配置,为患者提供更加…...
【Spring】事务
在软件开发中,事务确保一组操作要么全部成功,要么全部失败,这对于数据库操作尤为重要,因为任何单一操作的失败都可能导致数据不一致。Spring 事务管理通过 Transactional 注解实现,能够轻松地在数据层和业务层维护数据…...
canvas+fabric实现时间刻度尺(二)
前言 我们前面实现了时间刻度尺,鼠标移动显示时间,接下来我们实现鼠标点击某个时间进行弹框。 效果 实现 1.监听鼠标按下事件 2.编写弹框页面 3.时间转换 <template><div><canvas id"rulerCanvas" width"1200"…...
IPv6的过度技术
如何界定手动与自动? 主要是隧道目标地址能否自动获取 👯1. 双栈 必须支持IPv4和IPv6协议 链接双栈网络的接口必须同时配置v4和v6地址 路由器能够根据二层标记识别协议,type:0x0800代表IPV4,type:0x…...
介绍 Apache Spark 的基本概念和在大数据分析中的应用。
Apache Spark是一个开源的大数据处理框架,可用于高速处理和分析大规模数据集。它可以在分布式集群上运行,并且具有内存计算的能力,因此可以比传统的批处理框架更快地处理数据。 在Spark中,数据被表示为弹性分布式数据集ÿ…...
VA01/VA02检查增强
VA01/VA02检查增强 一、增强描述 VA01/VA02创建或修改SO时候,在点击“保存”按钮的节点,客户需求对一些约束条件进行检查,此处以 SO行项目对应的“利润中心”字段必输为例。通过查询更多的增强:SPRO–销售和分销–系统修正–用户…...
基于SpringBoot和Leaflet的全球机场空间分布可视化实战
目录 前言 一、航空机场的空间模型 1、空间表简介 2、数据查询 二、机场WebGIS空间分布可视化 1、后台数据查询 2、Leaflet页面开发 三、WebGIS分析 1、全球航空格局 2、我国机场影像 四、总结 前言 时光轻轻挥别2024,来到了2025年。在崭新的2025年里&am…...
FPGA交通灯实现
1 原理 FPGA(现场可编程门阵列)交通灯实现原理主要是基于硬件描述语言(如VHDL或Verilog)编程,通过FPGA内部的逻辑单元和寄存器来实现交通灯的控制功能。以下是对FPGA交通灯实现原理的详细解释: 一、交通灯的基本功能 交通灯的主要功能包括红灯、黄灯和绿灯的显示,以及…...
厦门大学联合网易提出StoryWeaver,可根据统一模型内给定的角色实现高质量的故事可视化
厦门大学联合网易提出StoryWeaver,可以根据统一模型内给定的角色实现高质量的故事可视化。可根据故事文本生成与之匹配的图像,并且确保每个角色在不同的场景中保持一致。本文的方法主要包括以下几个步骤: 角色图构建:设计一个角色…...
【Rust自学】8.1. Vector
喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 8.1.0. 本章内容 第八章主要讲的是Rust中常见的集合。Rust中提供了很多集合类型的数据结构&…...
华为OD机试真题---服务器广播
华为OD机试中的“服务器广播”题目是一个经典的算法问题,通常涉及图论和连通分量的概念。以下是对该题目的详细解析: 一、题目描述 服务器之间可以通过网络进行连接,连接方式包括直接相连和间接连接。给出一个NN的数组(矩阵&…...
又一年。。。。。。
2024,浑浑噩噩的一年。 除了100以内的加减法(数据,数据,还是数据。。。。。。),似乎没做些什么。 脸盲症越来越重的,怕是哪天连自己都不认得自己的了。 看到什么,听到什…...
【JAVA高级篇教学】第六篇:Springboot实现WebSocket
在 Spring Boot 中对接 WebSocket 是一个常见的场景,通常用于实现实时通信。以下是一个完整的 WebSocket 集成步骤,包括服务端和客户端的实现。本期做个简单的测试用例。 目录 一、WebSocket 简介 1. 什么是 WebSocket? 2. WebSocket 的特…...
Kotlin在医疗大健康域的应用实例探究与编程剖析(下)
四、Kotlin医疗编程实例分析 4.1 移动医疗应用实例 4.1.1 患者健康监测应用 在当今数字化医疗时代,患者健康监测应用为人们提供了便捷的健康管理方式。利用Kotlin开发的患者健康监测应用,能够实时采集患者的各类生理数据,如心率、血压、血氧饱和度等,并通过直观的可视化…...
Oracle Dataguard(主库为 Oracle 11g 单节点)配置详解(3):配置备用数据库
Oracle Dataguard(主库为 Oracle 11g 单节点)配置详解(3):配置备用数据库 目录 Oracle Dataguard(主库为 Oracle 11g 单节点)配置详解(3):配置备用数据库一、…...
LeetCode算法题——移除元素
题目描述 给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作࿱…...
七大设计原则之开闭原则
目录 一、什么是开闭原则? 二、如何做到开闭原则? 1、面向接口或抽象类编程 2、依赖注入 3、单一职责原则 三、是不是为了满足开闭原则就要一味的追求代码的扩展性? 一、什么是开闭原则? 相信很多人都听说过这个原则&#x…...
【stm32+K210项目】基于K210与STM32协同工作的智能垃圾分类系统设计与实现(完整工程资料源码)
视频效果演示: 基于K210与STM32协同工作的智能垃圾分类系统设计与实现 目录: 目录 视频效果演示: 目录: 项目简介: 一、设计目的: 1.1 项目背景 1.2 设计意义: 二、硬件部分: 2.1 st…...
Ps:创建数据驱动的图像
在设计实践中,常常需要处理大量内容变化但设计格式统一的任务,例如批量生成名片、工作证、学生证、胸牌、奖状或证书甚至图册。这些工作如果逐一手动制作,不仅耗时费力,还容易出错。 为解决这一问题,Photoshop 提供了强…...