Unity-Mirror网络框架-从入门到精通之Benchmark示例
文章目录
- 前言
- 什么是Benchmark?
- Benchmark 简要说明
- Benchmark示例
- BenchmarkNetworkManager
- MonsterMovement
- PlayerMovement
- InterestManagement
- 性能指标
- BenchmarkIdle示例
- BenchmarkPrediction示例
- BenchmarkStinkySteak示例
前言
在现代游戏开发中,网络功能日益成为提升游戏体验的关键组成部分。Mirror是一个用于Unity的开源网络框架,专为多人游戏开发设计。它使得开发者能够轻松实现网络连接、数据同步和游戏状态管理。本文将深入介绍Mirror的基本概念、如何与其他网络框架进行比较,以及如何从零开始创建一个使用Mirror的简单网络项目。

什么是Benchmark?
Benchmark示例 通常用于测试和评估Mirror网络框架在不同场景下的性能表现。该示例可以通过实施多种网络条件来测量服务器和客户端之间的数据传输速度、延迟、带宽使用情况以及不同数量的同时连接用户对整体性能的影响。
在测试过程中,开发者可以观察到游戏在进行高并发情况下的响应能力,例如在多人游戏场景中,如何处理大量玩家的输入、状态同步和事件广播等。同时,该示例还可以帮助开发者识别潜在的性能瓶颈,并对代码进行优化,以便实现更流畅的用户体验。
通过这些基准测试,开发者能够获取关键的性能指标,从而更好地调整游戏的网络架构和优化策略,以提高整个平台的稳定性和反应速度,同时确保用户在游戏中能够获得最佳的游戏体验。
Benchmark 简要说明
Mirror的Example包含哪些 基准测试 示例呢?
- 1.Benchmark:这个示例用于基准测试网络性能,通常会测试数据传输速率、延迟等网络参数,以帮助开发者评估他们的网络实现。
- 2.BenchmarkIdle:这个示例主要用于在空闲状态下进行基准测试,目的是评估在没有任何活动情况下的网络性能。这有助于理解网络在闲置时的行为情况。
- 3.BenchmarkPrediction:这个示例涉及到网络预测技术,通常用于展示如何在网络延迟情况下进行状态预测,以提高游戏的流畅度和响应性。
- 4.BenchmarkStinkySteak:这是一个更具趣味性的示例,通常用于展示服务器与客户端之间的交互。可能涉及一些有趣的机制或模拟网络延迟的场景,以帮助开发者理解网络通信是如何工作的。
这些示例可以帮助开发者更好地理解 Mirror 的功能和用法,并进行性能优化。
Benchmark示例
BenchmarkNetworkManager
基准测试的NetworkManager,主要是在StartServer后,创建了1000个自由飘荡的盒子,代表我们的大场景中的Monster。
逻辑很简单,就是SpawnAll,克隆1000个游戏对象,并且调用NetworkServer.Spawn(go),同步到网络中。
public class BenchmarkNetworkManager : NetworkManager{public GameObject spawnPrefab;public int spawnAmount = 5000;public float interleave = 1;void SpawnAll(){float sqrt = Mathf.Sqrt(spawnAmount);float offset = -sqrt / 2 * interleave;int spawned = 0;for (int spawnX = 0; spawnX < sqrt; ++spawnX){for (int spawnZ = 0; spawnZ < sqrt; ++spawnZ){if (spawned < spawnAmount){GameObject go = Instantiate(spawnPrefab);float x = offset + spawnX * interleave;float z = offset + spawnZ * interleave;go.transform.position = new Vector3(x, 0, z);NetworkServer.Spawn(go);++spawned;}}}}public override void OnStartServer(){base.OnStartServer();SpawnAll();}
MonsterMovement
这个脚本是模拟MMORPG中的Monster,在大场景中自由的移动。
这里着重说一下,Update函数是模拟怪物自由移动的,
但是Update上面有一个[ServerCallback]修饰,代表这是一个服务器才会执行的函数。
在Mirror框架中,如果一个函数被[Server]或者[ServerCallback]修饰,那么他就代表仅在服务器执行,客户端不执行。
这里相当于在服务器直接模拟了大量的AI怪物的移动。保证了不同客户端中显示的AI物体的同步。
public class MonsterMovement : NetworkBehaviour{public float speed = 1;public float movementProbability = 0.1f;public float movementDistance = 20;public override void OnStartServer(){start = transform.position;}[ServerCallback]void Update(){}}
PlayerMovement
PlayerMovement模拟的是玩家自由控制移动。纯客户端执行。
由于Player对象上有NetworkTransform组件,所以它的位置等信息会实时同步给其他客户端。
当我们在场景中走动的时候,我们发现可以看到的Monster,会根据自己的位置变化,距离Player位置近的会显示,距离远的会隐藏。这个是什么道理呢?
原来是Mirror给我们做了一个网络优化,在NetworkManager游戏对象上面,有一个组件名字叫:SpatialHashingInterestManagement(空间哈希兴趣管理),是一种用于优化网络游戏中对象的管理和交互的方法。它通过将游戏世界划分为多个小区域(或“哈希桶”),来决定哪个玩家需要接收哪些对象的信息,从而提高性能并减少不必要的数据传输。
他就类似在做大世界的MMORPG时,只显示距离我们近的范围的AI怪物,并非全地图绘制和执行所有怪物的逻辑的优化。
InterestManagement
Interest管理器,它的原理就是相当于把地图划分成了无数的格子,然后我们只能看到距离我们相近的9个格子内的网络对象。
如下图所示:

当我们在一个非常大的世界游戏中时,与其将完整的世界状态发送给每个玩家,不如考虑仅将玩家周围的内容发送给玩家。
Mirror给我们提供了InterestManagement的主要原因:
- 1.规模:想象一下魔兽世界。将整个世界发送给每个玩家将是疯狂的。为了扩展到数千个连接,我们只需要发送与任何给定玩家相关的内容。
- 2.可见性:在像 DotA/英雄联盟这样的 MOBA 游戏中,并不是每个人都应该一直看到其他人。玩家应该只看到自己的团队和周围的怪物。不仅如此,玩家还不应该看到墙后等。
- 3.作弊:在像 Counter-Strike 这样的游戏中,玩家自然看不到墙后的敌人,因为相机不会渲染它们。但是,如果整个世界状态在内存中都是已知的,那么黑客无论如何都可以利用这一点,将玩家显示在墙后。
InterestManagement是一个好主意。
Mirror给我们提供了很多内置的Interest Management组件
选择 Network Manager 并添加一个内置的 Interest Management 组件。
- 1.Spatial Hashing Interest Management:以前我们 Vector3.Distance 根据连接实体距离来判断。现在,我们将每个生成的实体放入一个 Grid 中,对于每个连接,我们将所有 8 个相邻的 Grid 条目都发送到客户端。这是非常快的。在早期的 uMMORPG 测试中,它比距离检查快 30 倍。该算法不太复杂,因此可以很好地扩展到大量实体。
- 2.Distance Interest Management:是简单的通过距离判断,来把范围内的连接发送给客户端,是InteractManager的最简单粗暴的做法。但是缺点就是,通过距离来判断每个连接成本较高。
- 3.Scene Interest Management:场景Interest 管理与附加场景一起使用,将对象联网到具有物理隔离的子场景。这意味着,即使您在服务器上加载了同一子场景的多个实例,对象之间的碰撞等也只会发生在该子场景内,而不会干扰其他子场景。
- 4.Scene Distance Interest Management:是上述 Scene 和 Distance 的组合。
- 5.Match Interest Management :匹配Interest管理,适用于非物理游戏,如纸牌、棋盘、街机游戏。
- 6.Team Interest Management:用于限制对团队成员的联网对象的可见性。这也可以用于仅限所有者的项目,取代 Network Owner Checker。
性能指标

在Benchmark示例中,您看到的参数主要用于监控和评估网络性能,具体含义如下:
- buffer:用于存储网络数据包的缓冲区。通常在网络传输中,数据包会被暂时存储在缓冲区中,以便后续处理或发送。
- driftEMA:表示“漂移的指数移动平均”(Exponential Moving Average of Drift)。这是一个用于平滑变量的统计量,帮助减少波动并提供更稳定的值,通常用于测量时间戳的漂移或延迟变化。
- DelTimeEMA:表示“延迟时间的指数移动平均”(Exponential Moving Average of Delay Time)。此参数用于跟踪网络延迟的平均值,以便评估网络响应的稳定性。
- BTM:可能代表“带宽时间测量”(Bandwidth Time Measurement),用于衡量网络在一定时间内能够传输的数据量,帮助评估网络性能。
- RTT:表示“往返时间”(Round-Trip Time),是从发送数据包开始,到接收到确认的时间。RTT是网络延迟的重要指标。
- PredErrUNADJ:表示“未调整的预测误差”(Unadjusted Prediction Error),用于测量在不调整任何参数的情况下,预测的值与实际值之间的差异。
- PredErrADJ:表示“调整后的预测误差”(Adjusted Prediction Error),与未调整的预测误差相似,但在计算时可能考虑了某些调整因素,从而得到更精确的预测效果。
这些参数共同用于评估和优化网络性能,特别是在多人游戏中,以帮助开发者理解网络延迟和数据传输的表现。
BenchmarkIdle示例
该示例,使用大多数空闲对象进行基准测试,以测试dirtyObjects技术。
这次创建的额对象都是空闲不动的,他们的数量大概有10000个
这产生了大量的流量。
该测试需要Telepathy才能不断开客户端。

这个示例的代码比较简单,就是纯创建10000个cube矩阵。
如下所示:
public class BenchmarkIdleNetworkManager : NetworkManager{[Header("Spawns")]public int spawnAmount = 10_000;public float interleave = 1;public GameObject spawnPrefab;[Range(0, 1)] public float spawnPositionRatio = 0.01f;System.Random random = new System.Random(42);void SpawnAll(){//for循环,创建10000个目标}public override Transform GetStartPosition(){startPositions.RemoveAll(t => t == null);if (startPositions.Count == 0)return null;int index = random.Next(0, startPositions.Count); // DETERMINISTICreturn startPositions[index];}public override void OnStartServer(){base.OnStartServer();SpawnAll();}
BenchmarkPrediction示例
Mirror的Predicted预测基准测试,是针对低端设备/VR进行的优化。
在不与对象交互的情况下,开销为零!
在交互过程中,开销来自同步和校正。
这个基准预测了不断同步和校正的对象。
=>真实游戏中效果会比这个示例好,因为这是我们可以用于分析的最坏情况!

NetworkManagerPredictionBenchmark适用于创建1000个物理小球,
RandomForce:是物理小球上的网络组件,用于不同客户端,不间断的给物理小球不停地施加随机的力,代表了真实物理世界中,不同客户端的玩家,同时操作处理同一个物理网络对象,造成的延迟和不稳定。
public class RandomForce : NetworkBehaviour{public float force = 10;public float interval = 3;PredictedRigidbody prediction;Rigidbody rb => prediction.predictedRigidbody;void Awake(){prediction = GetComponent<PredictedRigidbody>();}public override void OnStartClient(){float randomStart = Random.Range(0, interval);InvokeRepeating(nameof(ApplyForce), randomStart, interval);}[ClientCallback]void ApplyForce(){// calculate force in random direction but always upwardsVector2 direction2D = Random.insideUnitCircle;Vector3 direction3D = new Vector3(direction2D.x, 1.0f, direction2D.y);Vector3 impulse = direction3D * force;rb.AddForce(impulse, ForceMode.Impulse);CmdApplyForce(impulse);}[Command(requiresAuthority = false)] // everyone can call thisvoid CmdApplyForce(Vector3 impulse){rb.AddForce(impulse, ForceMode.Impulse);}
我们注意到,OnStartClient中,每个客户端都会开启一个定时器,不时的给小球施加一个力,然后调用了Command,把命令发送给服务器的同时,客户端自身也执行rb.AddForce,为什么这么做呢?
-
- 本地预测:
当客户端调用 rb.AddForce 时,它利用 PredictedRigidbody 组件在本地进行物理计算。这种方法让客户端可以立即感受到推动的效果,无需等待服务器的响应,从而提供更流畅、即时的反馈给玩家。
- 本地预测:
-
- 网络同步:
同时,CmdApplyForce 方法是一个 Command 方法,用于将力的应用请求发送到服务器。即使客户端立即对物体施加了力,该方法仍然会在服务器上执行一次相同的操作。这样,其他客户端也能看到这一变化,确保所有客户端的状态一致。
- 网络同步:
-
- 冲突说明:
由于物理计算是基于每个客户端本地进行的,所以如果网络延迟或不同的客户端施加的力不同,预测可能与服务器的实际状态有所偏差。
PredictedRigidbody 组件的设计宗旨是处理这些冲突。当服务器收到命令执行 rb.AddForce 时,物理效果会被应用,但如果与当前客户端的状态不一致,PredictedRigidbody 将自动处理这些调整,以确保同步。
- 冲突说明:
-
- 并发效果:
正如注释所述,这个方法允许每个连接的客户端对所有对象施加影响。因此,随着客户端数量的增加,场景的行为会变得更加复杂且动态。这种并发处理能够在基准测试时体现网络和同步机制的能力。
- 并发效果:
使用这种方式的目的是为了在保持快速响应和流畅玩家体验的同时,确保每个玩家都能看到一致的游戏状态,从而实现更好的用户体验和网络表现。

BenchmarkStinkySteak示例
提到这个示例,我们需要提到一个库 Unity 网络解决方案基准测试https://github.com/StinkySteak/unity-netcode-benchmark/
这个仓库,包含各种Unity网络框架项目对比基准测试的结果。目的就是公平的比较Unity的各个网络库的性能等差异。
网络库及版本包括如下:
| Netcode | Version | Transport |
|---|---|---|
| Fusion | 1.1.8 F 725 | Realtime |
| Fusion 2 | 2.0.0 RC 797 | Realtime |
| Netick | Netick 2 Beta 0.8.8 | LiteNetLib |
| NGO | 1.2.0 | Unity Transport |
| Fishnet | 3.11.10 | Tugboat |
| Mirror | 86.4.0 | KCP |
测试内容(2024年最新):
SineMoveYBehaviour:测试500个对象在Sine曲线Y周移动
SineMoveRandomBehaviour:测试500个对象在Sine曲线随机移动
WanderMoveBehaviour:测试500个对象随机漫游移动
测试结果如下:
Server Out (kBps)
| Mirror | NGO | Mirage | Fishnet | Netick | Fusion | Fusion 2 | kBps | |
|---|---|---|---|---|---|---|---|---|
| Move Y | 267 | 265 | 137 | 62 | 27 | 26 | 86 | kBps |
| Move All Axis | 307 | 306 | 124 | 103 | 87 | 81 | 79 | kBps |
| Move Wander | 459 | 461 | 138 | 145 | 96 | 125 | 85 | kBps |
NetworkTransform (Test ID: 2)
| NGO | Fusion 1 | Mirror | Fusion 2 | Fishnet | Netick | ||
|---|---|---|---|---|---|---|---|
| 0 Client | 0.13 | 0.131 | 0.060 | 0.031 | 0.034 | 0.029 | ms |
| 6 Clients | 0.18 | 0.135 | 0.067 | 0.034 | 0.034 | 0.0295 | ms |
| 12 Clients | 0.30 | 0.139 | 0.071 | 0.038 | 0.035 | 0.0299 | ms |
| 24 Clients | ERROR | 0.147 | 0.079 | 0.044 | 0.036 | 0.030 | ms |
SyncVar/NetworkProperty (Test ID: 4)
| NGO | Fusion 1 | Fusion 2 | Mirror | Netick | Fishnet | ||
|---|---|---|---|---|---|---|---|
| 0 Client | 0.030 | 0.026 | 0.025 | 0.017 | 0.0150 | 0.0115 | ms |
| 6 Clients | 0.039 | 0.028 | 0.029 | 0.021 | 0.0158 | 0.0116 | ms |
| 12 Clients | 0.049 | 0.031 | 0.032 | 0.024 | 0.0159 | 0.0116 | ms |
| 24 Clients | 0.078 | 0.038 | 0.038 | 0.030 | 0.0163 | 0.0116 | ms |
大家通过测试结果可以客观的看到各个网络库的差异,然后决定自己使用哪一个。
当然,我们也不能完全看这个数据来选,因为我们如果用这个网络库做项目的话,还要考虑其他几个更重要的问题:
1.网络库的社群是否活跃,如果将来遇到什么问题,是否有人解决或者帮助你。
2.网络库的仓库是否及时维护,如果有什么bug,作者能否及时更新?
3.网络库的API是否好学,易懂,符合个人喜好等等。
4.网络库是否收费,如何收费?
5.网络库的示例代码是否足够,学习难度大不大?
等等
通过综合对比后,我简单聊一下我的选择和原因。
不难看出,我选了Mirror,要不就不会有这篇文章了。
1.Fusion,是Photon光子旗下的,要说好用和稳定,那是没话说,但是它收费,而且国内使用受限。所以pass
2.NGO,unity的亲儿子,但是它的更新速度太慢,再加上之前UNet的无疾而终,导致我们大家现在不敢相信它。
3.Netick,国外用的比较多,国内几乎没人用,用的人也不多
4.FishNet,它是作者用了Mirror后发现了一些问题,自研了FishNet,所以性能肯定比Mirror强,本来我准备用它,但是它示例太少,用的人也少,导致我研究了一周左右,还是摸不着头脑,语法结构也有点懵逼。最后还发现它是半收费的,就是有些高级功能你必须付费才能使用。所以也pass了。
最后就选择Mirror了,虽然它有一些小问题,但是它的社群丰富,示例丰富,学习起来很快,虽然它速度没有FishNet快,但是我们普通的游戏,根本不会用那么多的游戏对象,因为那些基准测试都是在极限条件下进行的测试。普通的网络游戏,Mirror用起来都是没有问题的。
另外最打动我的一点是,已经有太多的游戏通过Mirror开发并且上线,群众的眼睛是血量的,所以我也选择了Mirror。
好了,这篇文张就到这里,希望对你能有所帮助。
相关文章:
Unity-Mirror网络框架-从入门到精通之Benchmark示例
文章目录 前言什么是Benchmark?Benchmark 简要说明Benchmark示例BenchmarkNetworkManagerMonsterMovementPlayerMovementInterestManagement性能指标 BenchmarkIdle示例BenchmarkPrediction示例BenchmarkStinkySteak示例 前言 在现代游戏开发中,网络功能…...
毕业项目推荐:基于yolov8/yolov5的行人检测识别系统(python+卷积神经网络)
文章目录 概要一、整体资源介绍技术要点功能展示:功能1 支持单张图片识别功能2 支持遍历文件夹识别功能3 支持识别视频文件功能4 支持摄像头识别功能5 支持结果文件导出(xls格式)功能6 支持切换检测到的目标查看 二、数据集三、算法介绍1. YO…...
今日头条ip属地根据什么显示?不准确怎么办
在今日头条这样的社交媒体平台上,用户的IP属地信息对于维护网络环境的健康与秩序至关重要。然而,不少用户发现自己的IP属地显示与实际位置不符,这引发了广泛的关注和讨论。本文将深入探讨今日头条IP属地的显示依据,并提供解决IP属…...
FPGA设计-如何使用后端工具
目录 简介 布线布局 设计前期 布局布线策略 兼谈如何做第一次布局布线 正确看待map之后的资源占用报告 简介 本章节主要说明Xilinx的一些后端工具能为我们做什么在什么情况下我们考虑使用这些工具至于这些工具具体如何使用可以看Xilinx提供的相关文件 可从www.xilinx.com…...
苍穹外卖04——Redis初入门 在店铺打烊or营业状态管理功能中的使用
Redis入门 redis简介 它以键值对的形式存储数据在内存中,并且以极高的性能和灵活性而著称,通常用于缓存、消息代理以及持久化数据。 - 基于内存存储,读写性能高- 适合存储热点数据(热点商品、资讯、新闻)- 企业应用广泛Windows版下载地址:https://github.com/microsoft…...
【MySQL关于数据库和表结构的增删查改】
数据库和表结构的基本语法 数据库命令关于字符集语法 表操作语法创建表查看表结构修改表修改表名增加字段同时修改字段名和字段数据类型仅修改字段数据类型删除字段 删除表 备份和恢复备份恢复 mysql -h 127.0.0.1 -P 3306 -u root -p mysql -u root -h 和 -p 默认 进入MySQL程…...
JVM实战—11.OOM的原因和模拟以及案例
大纲 1.线上系统突然由于OOM内存溢出挂掉 2.什么是内存溢出及哪些区域会发生内存溢出 3.Metaspace如何因类太多而发生内存溢出 4.无限制调用方法如何让线程的栈内存溢出 5.对象太多导致堆内存实在放不下而内存溢出 6.模拟JVM Metaspace内存溢出的场景(动态生成268个类占1…...
LLM - 使用 LLaMA-Factory 部署大模型 HTTP 多模态服务 教程 (4)
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/144881432 大模型的 HTTP 服务,通过网络接口,提供 AI 模型功能的服务,允许通过发送 HTTP 请求,交互大模型,通常基于云计算架构,无需在本地部署复杂的模型和硬件,…...
Clickhouse集群部署(3分片1副本)
Clickhouse集群部署 3台Linux服务器,搭建Clickhouse集群3分片1副本模式 1、安装Java、Clickhouse、Zookeeper dpkg -i clickhouse-client_23.2.6.34_amd64.deb dpkg -i clickhouse-common-static_23.2.6.34_amd64.deb dpkg -i clickhouse-server_23.2.6.34_amd64…...
刷服务器固件
猫眼淘票票 大麦 一 H3C通用IP 注:算力服务器不需要存储 二 刷服务器固件 1 登录固定IP地址 2 升级BMC版本 注 虽然IP不一致但是步骤是一致的 3 此时服务器会出现断网现象,若不断网等上三分钟ping一下 4 重新登录 5 断电拔电源线重新登录查看是否登录成功...
数据结构C语言描述9(图文结合)--二叉树和特殊书的概念,二叉树“最傻瓜式创建”与前中后序的“递归”与“非递归遍历”
前言 这个专栏将会用纯C实现常用的数据结构和简单的算法;有C基础即可跟着学习,代码均可运行;准备考研的也可跟着写,个人感觉,如果时间充裕,手写一遍比看书、刷题管用很多,这也是本人采用纯C语言…...
CSS——2.书写格式一
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title></head><body><!--css书写中:--><!--1.css 由属性名:属性值构成--><!--style"color: red;font-size: 20px;&quo…...
Elasticsearch 创建索引 Mapping映射属性 索引库操作 增删改查
Mapping Type映射属性 mapping是对索引库中文档的约束,有以下类型。 text:用于分析和全文搜索,通常适用于长文本字段。keyword:用于精确匹配,不会进行分析,适用于标签、ID 等精确匹配场景。integer、long…...
【NLP高频面题 - 分布式训练篇】ZeRO主要为了解决什么问题?
【NLP高频面题 - 分布式训练篇】ZeRO主要为了解决什么问题? 重要性:★★ 零冗余优化器技术由 DeepSpeed 代码库提出,主要用于解决数据并行中的模型冗余问题,即每张 GPU 均需要复制一份模型参数。 ZeRO的全称是Zero Redundancy …...
kubernetes-循序渐进了解coredns
文章目录 概要基础知识Kubernetes 集群中对对象名称的 DNS 流量解析 Kubernetes 集群外的名称的 DNS 流量CoreDNS 如何确定向哪个本地 DNS 请求解析?修改 CoreDNS 的配置 概要 CoreDNS 是 Kubernetes 的核心组件之一。只有在 Kubernetes 集群中安装了 容器网络接口…...
mysql8 从C++源码角度看 客户端发送的sql信息 mysql服务端从网络读取到buff缓存中
MySQL 8 版本中的客户端-服务器通信相关,特别是在接收和解析网络请求的数据包时。以下是对代码各个部分的详细解释,帮助您更好地理解这些代码的作用。 代码概述 这段代码主要负责从网络读取数据包,它包含了多个函数来处理网络数据的读取、缓…...
pygame飞机大战
飞机大战 1.main类2.配置类3.游戏主类4.游戏资源类5.资源下载6.游戏效果 1.main类 启动游戏。 from MainWindow import MainWindow if __name__ __main__:appMainWindow()app.run()2.配置类 该类主要存放游戏的各种设置参数。 #窗口尺寸 #窗口尺寸 import random import p…...
【Vim Masterclass 笔记08】第 6 章:Vim 中的文本变换及替换操作 + S06L20:文本的插入、变更、替换,以及合并操作
文章目录 Section 6:Transforming and Substituting TextS06L21 Inserting, Changing, Replacing, and Joining1 定位到行首非空字符,并启用插入模式2 在紧挨光标的下一个字符位置启动插入模式3 定位到一行末尾,并启用插入模式4 定位到光标的…...
Tailwind CSS 实战:动画效果设计与实现
在现代网页设计中,动画效果就像是一位优秀的舞者,通过流畅的动作为用户带来愉悦的视觉体验。记得在一个产品展示网站项目中,我们通过添加精心设计的动画效果,让用户的平均停留时间提升了 35%。今天,我想和大家分享如何使用 Tailwind CSS 打造优雅的动画效果。 设计理念 设计动…...
【动手学电机驱动】STM32-MBD(3)Simulink 状态机模型的部署
STM32-MBD(1)安装 Simulink STM32 硬件支持包 STM32-MBD(2)Simulink 模型部署入门 STM32-MBD(3)Simulink 状态机模型的部署 【动手学电机驱动】STM32-MBD(3)Simulink 状态机模型部署…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
DiscuzX3.5发帖json api
参考文章:PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下,适配我自己的需求 有一个站点存在多个采集站,我想通过主站拿标题,采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...
