当前位置: 首页 > news >正文

【Unity万人同屏插件】使用手册 保姆级教程 GPU动画 Jobs多线程渲染

【万人同屏插件】

基于Dots技术,高性能实现3D、2D Spine渲染、海量单位锁敌/碰撞检测。同时通过自定义BRG渲染器绕过对Entities包的依赖,也就是不用写ECS代码即可拥有Entities Graphics的高性能渲染,使用传统开发方式BRG接管Renderer组件。

可以大幅提升PC或移动平台的游戏帧数,GPU动画同样支持WebGL,对于开发小游戏也有着巨大性能提升。同时,转换为GPU动画后可以大幅减少动画文件大小,可用作包体大小优化。

适用于海量单位游戏项目突破技术门槛,同时也适用于任何需要做性能优化的项目。例如:割草、类吸血鬼、RTS、SLG、弹幕游戏,以及海量树木、植被、建筑渲染等。

Dots正式版发布于Unity2022.3 LTS版,因此强烈建议使用Unity 2022.3.x及以上版本,插件同样支持最新版Unity 6.

功能/性能测试Demo下载

https://pan.baidu.com/s/1ML0DC8s0RkkTAraN9maltw?pwd=blueicon-default.png?t=O83Ahttps://pan.baidu.com/s/1ML0DC8s0RkkTAraN9maltw?pwd=blue

网页版在线测试性能Unity Web Player | rvo_gpuanim_brgicon-default.png?t=O83Ahttp://efunny.com.cn/gpu_anim

插件获取【万人同屏插件】

首页-游戏开发资源商店-淘宝网PC店铺icon-default.png?t=O83Ahttps://shop106471535.taobao.com/

【万人同屏插件】实战项目mu'b

测试环境

系统:Windows 11

Unity:Unity 2022.3.45f1

CPU: i7-13700KF

GPU: RTX 3070 8G

GPU动画插件(支持3D\2D Spine):

兼容性

纯Shader实现的GPU动画,超高性能。插件支持Unity全平台,兼容WebGL,可用于H5/小游戏开发。支持动画事件、保留骨骼信息(动态获得骨骼节点位置/旋转/缩放)、2D Spine半透物体渲染顺序、动画平滑融合过渡(Pro)、LOD生成(Pro)。

实现原理

由于Animator或Spine动画都是CPU计算,因此存在性能瓶颈、并且蒙皮动画无法合批渲染,DrawCall大幅降低帧数(以性能测试demo为例,1w个Animator仅有8 fps)。

GPU动画是把Animator转换为GPU计算, Shader中播放动画。使用MeshRenderer或BRG渲染,自动合批渲染,大幅降低DrawCall。以性能测试demo为例, 1w个GPU动画117 fps; 而使用BRG渲染GPU动画,帧数高达800 fps

一、3D动画转GPU动画 

1. GPU动画转换工具界面

通过Unity顶部菜单Game Framework->GPU Animation->GPU Animation Converter打开工具界面

 GPU动画转换工具面板:

①拖入需要转换的Animator/Animation预制体;

②动画模式:支持GPU骨骼动画和顶点动画;推荐骨骼动画,功能更强大;

③合并网格:合并Mesh降低DC, 对于Spine动画将进行排序,确保半透物体渲染排序正确;仅支持共用相同材质的网格合并,对于不同材质、多张贴图的物体,可通过三方插件Mesh Baker先合并材质/贴图,再转换GPU动画。

④Animator相关设置,默认值即可。 如是否冻结根骨骼位置/旋转等;

⑤选择GPU动画shader, Spine动画要选择2D shader;也可生成GPU动画后再切换材质shader;

⑥需要烘焙到GPU动画贴图的Animation Clips 工具默认添加Animator中引用的所有Animation Clip;通过列表的索引值切换动画状态;

⑦把需要运行时获取transform值的骨骼节点拖到此处 转换为GPU动画后仍能实时获取到骨骼transform值;  此功能可使转换为GPU动画后骨骼信息不丢失,比如可以实时获取头部、手部位置;

2. GPU动画工具用法

①把Animator或Animation动画角色预制体拖入场景;

②把拖入场景的预制体拖入GPU动画转换工具的Input栏;

③拖动Animation Clips列表元素,组织好自己的动画索引对应的动画(可选);

④把需要保留骨骼transform信息的节点拖到Record Bones列表;

⑤点击Convert按钮,转换为GPU动画;

3. GPU动画资源

转换后会生成以下GPU动画文件:

①动画贴图。记录着动画数据;

②GPU动画Prefab。将原动画Prefab中的SkinnedMeshRenderer转换为了MeshRenderer,同时拥有动画播放功能和自动合批渲染;

③GPU动画帧事件,用于GPU动画播放时触发动画事件。工具默认会把Animation Clip文件中添加Event事件转换为GPU动画帧事件;

④GPU动画材质,由于是纯shader实现,因此可以不依赖任何脚本,仅修改材质属性切换动画;

⑤GPU动画Mesh,Mesh中寄存了某些信息,以便GPU动画Shader读取使用;

4. 自定义GPU动画Shader 

 插件使用Shader GraphAmplify Shader Editor封装好了函数节点,只需添加GPU动画节点连接顶点位置、顶点法线即可轻松实现自定义Shader

使用Amplify Shader Editor
使用Shader Graph

对于使用BRG渲染需要向Shader传递参数的情况:

由于每个渲染节点在GPU中都有一块连续的内存,以高效访问。对于自定义Shader添加的每个渲染物体实例需要单独设置的shader字段,需要修改BatchRendererComponent代码,参考_ClipId进行扩展参数。

例如:新增一个Vector4类型作为预留参数以供传递数据:

0. 重新计算单个渲染物体占用内存:

由于新增了一个Vector4字段,因此内存新增了4个float大小,需修改BRGUtility.kBytesPerInstance大小:

每个渲染物占GPU内存:两个4x3矩阵 + BaseColor(4个float) + ClipId(4个float) + 新增Vector4字段(4个float):

public static readonly int kBytesPerInstance = kSizeOfPackedMatrix * 2 + kSizeOfFloat4 * 3;

1. 定义Shader Property字段名:

int objectToWorldID = Shader.PropertyToID("unity_ObjectToWorld");
int worldToObjectID = Shader.PropertyToID("unity_WorldToObject");
int colorID = Shader.PropertyToID("_BaseColor");
int clipIdID = Shader.PropertyToID("_ClipId");
int userVec4ID = Shader.PropertyToID("_UserdataVec4");//新增vector4字段

2. 计算新增字段的起始内存:

...
int clipIdIndex = colorIndex + batchInstanceCount;
int userdataVec4Index = clipIdIndex + batchInstanceCount;
var drawBatch = new SrpBatch
{...clipIdIdx = clipIdIndex,userdataVec4Idx = userdataVec4Index
};

3. 重新计算metadata地址:

if (UseConstantBuffer)
{...metadataValues[3] = CreateMetadataValue(clipIdID, (clipIdIndex - offsetInFloat4) * kSizeOfFloat4, true);metadataValues[4] = CreateMetadataValue(userVec4ID, (userdataVec4Index - offsetInFloat4) * kSizeOfFloat4, true);
}
else
{...metadataValues[3] = CreateMetadataValue(clipIdID, clipIdIndex * kSizeOfFloat4, true);metadataValues[4] = CreateMetadataValue(userVec4ID, userdataVec4Index * kSizeOfFloat4, true);
}

4. 新增字段上传GPU:

修改UploadParallelJob代码,Ouput数据追加一行:

Output[srpBatch.userdataVec4Idx + j] = renderer.userdataVec4;

二、2D Spine转GPU动画

十代i5 + 1050显卡下依然性能强悍

实际上,只需要把Spine转换为Animator,就可以通过标题一的步骤把Animator转换为GPU动画

2d spine动画帧数提升数十倍?spine转gpu动画 2d spine动画 10w单位

1. Spine转Animator工具

①通过Unity顶部菜单栏 GameFramework->GPU Animation->Spine to Animator打开工具

②把Spine文件拖到工具,点击Bake按钮开始转换

2. Spine转GPU动画

 使用GPU Animation Converter把步骤1 Spine转换出的Animator预制体转换为GPU动画。

 注意:Spine通常是2D半透明物体,因此需要把GPU动画Shader切换为2D的Shader(如:GPUAnimation/2D/GPUBonesAnim2D)

三、GPU Animation LOD工具 [PRO版功能]

多线程渲染器支持LOD, 根据距离显示不同精度模型,大幅提升性能

1. 自动生成减面LODs

根据LOD 0 Mesh生成LOD 1~4简化Mesh; 

①此工具依赖三方插件MantisLOD,用于自动简化Mesh面数,同时尽量保留Mesh轮廓。安装MantisLOD后,解除代码GPUAnimationLODCreator.cs第一行注释即可使用功能:

#define ENABLE_MANTISLOD //安装MantisLOD插件后解除此行注释
...
#if ENABLE_MANTISLOD
using MantisLOD;
using MantisLODEditor;
#endif

②GameFramework->GPU Animation->GPU Animation LOD打开工具

2. 使用已有LOD Mesh生成(可选)

除了使用工具自动生成减面LOD Mesh, 当然也可以根据已有的Mesh直接生成LODs Mesh

四、武器挂载、动画事件、骨骼获取

武器挂载 帧事件 骨骼获取 视频教程

1. 武器挂载

①把武器作为GPU动画角色的子节点,修改材质shader为GPUAnimation/GPUAttachBoneLit,并将主角的动画贴图赋值到材质;

②通过修改武器材质的AttachBoneIndex来设置武器绑定到哪个骨骼

说明: 这里AttachBoneIndex对应的就是GPU动画工具界面RecordBones记录的骨骼节点索引

2. 动画事件

GPU动画事件触发时实时获取拳头骨骼位置

 转换GPU动画时会自动生成动画事件文件,如下图:

 默认情况下,工具是从Animation Clip文件读取动画事件,以key, value形式保存。key是触发帧,value是事件名。用户可直接修改此文件增删事件。

①. GPU动画帧事件用法:

使用GPUAnimation脚本,设置好Event Data:

 GPU动画事件实例代码:

using Cysharp.Threading.Tasks;
using GPUAnimation.Runtime;
using UnityEngine;public class GPUAnimEventDemo : MonoBehaviour
{GPUAnimation.Runtime.GPUAnimation m_GPUAnim;private void Start(){m_GPUAnim = GetComponent<GPUAnimation.Runtime.GPUAnimation>();//添加GPU动画事件监听m_GPUAnim.Events.AddListener(OnGPUAnimEventCallback);m_GPUAnim.GPUAnimMaterial.SetVector("_ClipId", new Vector4(4, Time.time, 0, 0));}private void OnDestroy(){m_GPUAnim.Events.RemoveListener(OnGPUAnimEventCallback);}/// <summary>/// GPU动画事件回调/// </summary>/// <param name="clipIndex">动画index</param>/// <param name="frame">触发帧</param>/// <param name="eventName">事件名</param>private void OnGPUAnimEventCallback(int clipIndex, int frame, string eventName){if (eventName == "DamageTrigger") //挥拳动画事件触发时在拳头位置发射小球{var boneData = GPUAnimationUtility.GetAttachBoneTransform(m_GPUAnim.GPUAnimMaterial, 1);//获取右手当前动画帧的位置GameObject ball = GameObject.CreatePrimitive(PrimitiveType.Sphere);ball.transform.localScale = Vector3.one * 0.2f;ball.transform.position = m_GPUAnim.transform.position + boneData.Position;_ = UniTask.Delay(1000).ContinueWith(() =>{Destroy(ball);});}}
}

②. BRG多线程渲染下GPU动画帧事件用法

为了应对海量单位下动画事件触发依然流畅,BRG组件专门提供了jobs多线程实现的事件触发检测函数:

public bool TryTriggerGPUAnimationEvents(out NativeQueue<GPUAnimTriggerInfo> triggerResults)

 代码示例:

 在Update中每帧调用,以批量检测动画事件触发

/// <summary>
/// 查询已经触发的GPU动画事件
/// </summary>
private void GPUAnimTriggerUpdate()
{if (BatchRendererComponent.Instance.TryTriggerGPUAnimationEvents(out var triggerResults)){while (triggerResults.TryDequeue(out var result)){if (m_Players.TryGetValue(result.AgentId, out BRG_Player unit)){//触发某个单位的GPU动画事件unit.OnGPUAnimationEvent(result.ResIndex, result.ClipIndex, result.TriggerAtFrame);}}triggerResults.Dispose();}
}

3. 骨骼获取

用于GPU动画运行时,实时获取某个骨骼节点的Transform信息;例如,角色持枪射击,子弹应从枪口位置创建发射(市面上其它GPU动画插件,转换GPU动画后骨骼信息全部丢失,无法获取枪口位置)。

GPUAnimationUtility类提供了多种获取当前GPU动画帧某个骨骼的transform信息的接口

例如,获取RecordBones记录的索引为1的骨骼transform信息:

GPUAnimationUtility.GetAttachBoneTransform(GPUAnimMaterial, 1);

 BRG多线程渲染接口同样提供了封装好的接口:

BatchRendererComponent.Instance.GetAnimationAttachBone(m_RendererNodeId, boneIndex)

五、动画平滑过渡、融合 [PRO版功能]

3D/2D Spine动画平滑切换,支持控制过渡时长

直接把GPU动画材质的Shader切换为支持平滑过渡的Shader即可,如:GPUAnimation/GPUBonesAnimMergeLit

ClipId:该参数用于切换动画,对于不支持动画融合的Shader, x是动画index, y是开始播放的时间(Time.time);

对于支持动画融合的Shader,z是上个动画的index,w是上个动画的播放时间,x是要切换到的动画index,y是动画第一帧开始的时间,也就是不算融合时间(Time.time + 动画过渡消耗时间)

AnimTransDration:动画平滑过渡(融合)速度

GPU动画使用限制

尽管已经实现大量GPU动画功能,但依然比不上高级动画系统的功能,如IK、Avatar Mask是不支持的。

由于GPU动画贴图储存动画信息有限,目前支持记录Transform信息和GameObject的显示隐藏。对于3D动画完全足够。但对于2D Spine动画,有时会记录特殊的关键帧,如修改颜色、修改贴图等,这些GPU动画是不支持的,但仍可以通过显示隐藏实现, 例如,皮肤A切换到皮肤B,可以通过隐藏皮肤A,显示皮肤B以实现换装功能。

BRG多线程渲染(BatchRenderComponent):

使用Entities Graphics的底层接口BatchRendererGroup,自己组织内存、显存,利用Dots技术栈的高性能,使用Jobs多线程提交渲染数据到GPU,通过合批一次渲染大量单位,从而巨大提升渲染性能。

渲染10万个3D模型, 帧数148 fps

BRG多线程合批渲染 LODs功能用法

性能表现 

使用BRG组件渲染1w个GPU动画人物,800 fps

使用MeshRenderer渲染1w个GPU动画人物,117 fps:

直接Animator(SkinnedMeshRenderer)渲染1w个GPU动画人物, 10 fps:

一、注册要渲染的物体

 首先要把需要用BRG组件渲染的物体,添加到RendererResources列表。

1. Mesh, Material:把GPU动画转换工具生成的GPU动画文件(材质、Mesh)添加到Renderer Resources列表;

2. Capacity:该物体最大渲染数量,为了追求极致性能,BRG将根据最大渲染数量分配一片定长内存,以避免渲染单位数量变化导致重新分配存储拷贝数据造成性能消耗。

3. GPU Anim Event Data: GPU动画事件文件, 若该物体无动画事件可不设置;

4. Lod Distances:x,y,z,w分别为LOD 0 ~ 4各个等级的距离;距离越近显示的模型面数越高。此功能需勾选Enable LOD; 

5. 开启LOD功能:勾选Enable LOD, 然后把GPU Animation LOD工具生成合并后的LODs Mesh作为RendererResource的Mesh即可;

二、BatchRendererComponent接口用法

1. 添加一个物体

m_RendererId = BatchRendererComponent.Instance.AddRenderer(resId, pos, rotation, scale);

 其中,resId就是Renderer Resources列表中注册的渲染物的索引index;

返回值为RendererNodeId,可通过RendererNodeId设置渲染物的属性,如切换GPU动画:

BatchRendererComponent.Instance.SetRendererClipId(m_RendererId, animIndex);

2. 移除一个物体

BatchRendererComponent.Instance.RemoveRenderer(m_RendererId);

RVO多线程避让

Unity Dots 10万人同屏RVO避障是一种什么体验? 3D人物带动画,不使用ECS

1. 添加RVO单位

AddAgent()会返回一个RVOAgent对象,可通过此对象设置各种rvo参数

m_RVO = RVOComponent.Instance.AddAgent(position);

2. 移除RVO单位

RVOComponent.Instance.RemoveAgent(m_RVO);

3. RVO属性功能 

avoidWeight:避让权重,比如高级兵不给小兵让路,小兵需要给高级兵让路,以避免高级兵被小兵挡住的情况。只需设置avoidWeight,取值0-1,值越小越不让路。

searchRadius:寻敌半径

searchCount:寻敌数量,==1,单体攻击;>1, 群体攻击

targetPosition:移动目标点

camp:单位所属阵营,数据类型是位枚举,所以支持单个单位多个阵营(以满足用户特殊需要)

searchTag:标记自己的标签,数据类型是位枚举,支持标记多个标签;此标签配合ignoreSearchTag使用,用于精准控制寻敌过滤目标;例如:敌方阵营有个飞行单位,我方阵营的近战单位虽然属于敌对阵营,但近战单位不可能攻击到高空飞行目标。

ignoreSearchTag:寻敌时忽略掉ignoreSearchTag位枚举中包含的searchTag,用于精准控制筛选寻敌

collisionEnabled:rvo单位之间是否碰撞,为false时rvo之间将会重叠穿模

navigationEnabled:rvo单位是否自动移动,设为false后,即可通过rvo的position来随意设置位置;例如:击飞效果,单位受到攻击后被击飞,就可以通过设置navigationEnabled为false,然后自行设置position实现击飞效果,落地后再设置navigationEnabled为true即可从击飞落地位置重新移动。

4. 障碍物

①添加圆形障碍物:把CircleObstacle脚本挂到障碍物GameObject上即可

②添加举行障碍物:把BoxObstacle脚本挂到障碍物GameObject上即可

③添加边界障碍物:把EdgeObstacle脚本挂到障碍物GameObject上即可,通过面板参数添加边界顶点位置

④扩展自定义障碍物:自定义类继承ShapeObstacleBase,重写方法即可

海量单位多线程寻敌/碰撞检测:

Unity弹幕游戏, RVO红蓝对抗 割草游戏 海量单位高性能索敌攻击方案压测

方案是通过Jobs多线程批量查询单位,支持查询最近单位、范围内单位等,通过RVOComponent提供的接口查询

具体使用方法可参考插件提供的demo, EnemiesSearchDemo.cs

1. 查询最近单位

SearchAgentsNearest:查询最近的单位

2. 查询范围内目标

SearchAgentsWithin:查询半径内的目标,返回数量为rvo的searchCount,也支持指定个数

3. 查询范围内多目标(AOE) 

var ids = rvo.SearchAgentsWithin(tempQueryPoints, damageRadius, maxDamageCount);
for (int i = 0; i < ids.Length; i += maxDamageCount)
{int indexOffset = i * maxDamageCount;for (int j = 0; j < maxDamageCount; j++){int agentId = ids[indexOffset + j];if (agentId <= 0) break;if (m_Players.ContainsKey(agentId)){m_Players[agentId].ApplyDamage(100);}}
}

注意事项:

一、BRG跨平台兼容性

BRG兼容性可参考官方文档:Unity - Manual: Getting started with BatchRendererGroupicon-default.png?t=O83Ahttps://docs.unity3d.com/2022.3/Documentation/Manual/batch-renderer-group-getting-started.html

渲染管线:目前支持URP、HDRP、自定义SRP

兼容平台:目前不支持WebGL

  • Windows using DirectX 11
  • Windows using DirectX 12
  • Windows using Vulkan
  • Universal Windows Platform
  • Linux using Vulkan
  • macOS using Metal
  • iOS
  • Android (Vulkan and OpenGL ES 3.x)
  • PlayStation 4
  • PlayStation 5
  • Xbox One
  • Xbox Series X and Xbox Series S
  • Nintendo Switch
  • Google Stadia

二、打包设置

1. URP Rendering Path选择Forward+ (Forward+才能发挥BRG最大性能)

2. BatchRendererGroup Shader变体选择 Keep All

3. 打包后GPU Spine动画渲染顺序异常

BatchRendererComponent在Unity6下开启渲染排序(Sorting Position)后,编辑器下渲染顺序正常,打包后渲染顺序错误:

猜测这是BatchRendererGroup的bug,当项目只使用一个场景,没有任何场景切换时就会复现这个bug;

解决方法:使用两个场景,例如:场景A是空场景, 场景B是游戏场景,游戏开始后Additional方式加载场景B或者切换到场景B,这样渲染顺序就不会出现异常。

4. 打包WebGL

常见问题1:编辑器或其它平台正常,打包WebGL渲染异常;

解决方法:如果PlayerSettings设置的为WebGL 1,Shader Model需设置为2.0;WebGL2可设置Shader Model为3.0.

使用Amplify Shader Editor打开GPU动画Shader,设置Shader Model: 

相关文章:

【Unity万人同屏插件】使用手册 保姆级教程 GPU动画 Jobs多线程渲染

【万人同屏插件】 基于Dots技术&#xff0c;高性能实现3D、2D Spine渲染、海量单位锁敌/碰撞检测。同时通过自定义BRG渲染器绕过对Entities包的依赖&#xff0c;也就是不用写ECS代码即可拥有Entities Graphics的高性能渲染&#xff0c;使用传统开发方式BRG接管Renderer组件。 …...

结合前端的响应式开发深入理解设备像素比

前端响应式开发中设备像素比是一个绕不开的概念&#xff0c;彻底理解这个概念&#xff0c;我们首先要梳理清楚屏幕设备的物理像素&#xff08;Physical Pixel&#xff09;、逻辑像素&#xff08;Logical Pixel&#xff09;以及css像素&#xff08;px&#xff09;之前的区别和联…...

QT c++ 按钮 样式 设置按下和松开的背景颜色

上一篇文章&#xff0c;需要自定义类&#xff0c;本文使用样式设置按下和松开的背景颜色。 1.头文件 #ifndef WIDGET_H #define WIDGET_H #include <QWidget> //#include "CustomButton.h" #include <QVBoxLayout> //#include <QLinearGradient>…...

解决Docker冲突问题

错误&#xff1a;docker-ce-cli conflicts with 2:docker-1.13.1-210.git7d71120.el7.centos.x86_64 错误&#xff1a;docker-ce conflicts with 2:docker-1.13.1-210.git7d71120.el7.centos.x86_64 您可以尝试添加 --skip-broken 选项来解决该问题 您可以尝试执行&#xff1a;…...

C++之闭散列哈希表

目录 unordered_set和unordered_map 哈希概念 哈希表基本结构 哈希冲突 线性探测​编辑 二次探测 前几期我们学习了红黑树和红黑树的模拟实现&#xff0c;最终使用红黑树封装了map和set。本期开始我们将学习下一个重要的知识点---哈希表&#xff0c;最终使用哈希表封装u…...

微信小程序map组件所有markers展示在视野范围内

注意&#xff1a;使用include-points属性不生效&#xff0c;要通过createMapContext实现 <template><view class"map-box"><map id"map" class"map" :markers"markers" :enable-traffic"true" :enable-poi&…...

Ubuntu平台虚拟机软件学习笔记

Ubuntu平台上常见虚拟机软件 VirtualBox [Download]KVM/QEMU 1. VirtualBox 1.1 查看安装版本 VBoxManage -V2. KVM/QEMU KVM: Kernel-based Virtual Machine QEMU: Quick EMUlator 通义千问&#xff1a; virt-manager 既不是QEMU也不是KVM&#xff0c;而是用于管理和创建…...

EasyExcel数据的导入导出

1.easyExcel简介 EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。 他能让你在不用考虑性能、内存的等因素的情况下&#xff0c;快速完成Excel的读、写等功能。 EasyExcel 的主要特点如下&#xff1a; 1、高性能&#xff1a;EasyExcel 采用了异…...

CSS Grid 布局全攻略:从基础到进阶

文章目录 一.Grid 是什么二.示例代码1. 基础使用 - 固定宽高2.百分百宽高3.重复设置-repeat4.单位-fr5.自适应6.间距定义其他 一.Grid 是什么 CSS 中 Grid 是一种强大的布局方式&#xff0c;它可以同时处理行和列 Grid 和Flex有一些类似&#xff0c;都是由父元素包裹子元素使用…...

C语言的语法

C语言的语法与应用探讨 C语言作为一种高效的程序设计语言&#xff0c;自1970年代问世以来&#xff0c;一直在科学计算、系统编程、嵌入式系统等领域中扮演着重要角色。本文将深入探讨C语言的基本语法、数据结构、控制结构以及其在实际应用中的重要性。 一、C语言基础 1.1 数…...

Go中的context 包使用详解

context 包在 Go 中非常重要&#xff0c;特别是在处理并发和超时的场景下&#xff0c;它能让你在多个 goroutine 之间传递取消信号、超时控制或其他控制信息。context 是 Go 并发模型中的一个重要工具&#xff0c;尤其适用于 HTTP 请求、数据库操作、分布式系统等场景。 1. 基…...

通俗易懂之线性回归时序预测PyTorch实践

线性回归&#xff08;Linear Regression&#xff09;是机器学习中最基本且广泛应用的算法之一。它不仅作为入门学习的经典案例&#xff0c;也是许多复杂模型的基础。本文将全面介绍线性回归的原理、应用&#xff0c;并通过一段PyTorch代码进行实践演示&#xff0c;帮助读者深入…...

机器学习模型评估指标

模型的评估指标是衡量一个模型应用于对应任务的契合程度&#xff0c;常见的指标有&#xff1a; 准确率&#xff08;Accuracy&#xff09;: 正确预测的样本数占总样本数的比例。适用于类别分布均衡的数据集。 精确率&#xff08;Precision&#xff09;: 在所有被预测为正类的样…...

嵌入式软件C语言面试常见问题及答案解析(三)

嵌入式软件C语言面试常见问题及答案解析(三) 上一篇已经足够长了,再长也就有点不礼貌了,所以在这儿继续来总结分享那个面试中遇到的题目,文中的问题和提供的答案或者代码均代表个人的理解,如有不合理或者错误的地方,欢迎大家批评指正。 本文中题目列表 1. 编码实现子串定…...

LeetCode:165. 比较版本号(双指针 Java)

目录 165. 比较版本号 题目描述&#xff1a; 实现代码与解析&#xff1a; 双指针 原理思路&#xff1a; 165. 比较版本号 题目描述&#xff1a; 给你两个 版本号字符串 version1 和 version2 &#xff0c;请你比较它们。版本号由被点 . 分开的修订号组成。修订号的值 是它…...

Golang中遇到“note module requires Go xxx”后的解决方案,不升级Go版本!

前几天&#xff0c;需要对一个两年前写的项目添加点儿新功能&#xff0c;需要用到一个 Http 客户端包&#xff0c;于是就用了 https://github.com/go-resty/resty 这个插件包。 我先是直接在项目根目录下执行了以下包的安装命令&#xff1a; go get -v github.com/go-resty/res…...

ubuntu编译ijkplayer,支持rmvb以及mkv

1. 准备环境 sudo apt-get update apt install gcc yasm cmake python p7zip-full vim pkg-config autoconf automake build-essential dos2unix mercurial cmake-curse-gui -y apt-get -y --force-yes install libass-dev libtheora-dev libtool libva-dev libvdpau-dev libv…...

mysql之sql的优化方案(重点)

1、全字段匹配是最棒的 假如一个Staffs 这个表&#xff0c;将 name,age ,pos 组合成了一个联合索引&#xff0c;在where条件下&#xff0c;能够使用到的索引越多越好。 EXPLAIN SELECT * FROM staffs WHERE NAME July; EXPLAIN SELECT * FROM staffs WHERE NAME July AND age…...

使用Qt实现json数据的格式检测并序列化输出 Qt5.4.0环境

问题&#xff1a; 使用 Qt 实现 JSON 数据的格式检测&#xff0c;并输出各个键值 代码&#xff1a; widget.h #include <QWidget> #include <QJsonDocument> /*序列化 反序列化(F1查看帮助文档)*/ #include <QJsonObject> /*利用对象代表了一段json数据*/ …...

Internet协议原理

文章目录 考试说明Chapter 0: 本书介绍Chapter 1: Introduction And Overview 【第1章&#xff1a;引言与概述】Chapter 2: Overview Of Underlying Network Technologies 【第2章&#xff1a;底层网络技术的回顾】Chapter 3: Internetworking Concept And Architectural Model…...

国标GB28181-2022视频平台EasyGBS小知识:局域网ip地址不够用怎么解决?

在局域网中&#xff0c;IP地址不足的问题通常不会在小型网络中出现&#xff0c;但在拥有超过255台设备的大型局域网中&#xff0c;就需要考虑如何解决IP地址不够用的问题了。 在企业局域网中&#xff0c;经常会出现私有IP地址如192.168.1.x到192.168.1.255不够用的情况。由于0…...

CentOS 使用 yum 方式安装 Nginx

CentOS 使用 yum 方式安装 Nginx 文章目录 CentOS 使用 yum 方式安装 Nginx1、Nginx 安装前提条件步骤 1&#xff1a;更新系统软件包步骤 2&#xff1a;查看 Nginx 相关的软件包步骤 3&#xff1a;安装 Nginx步骤 4&#xff1a;启动并启用 Nginx步骤 5&#xff1a;验证 Nginx 是…...

Spring Boot教程之五十一:Spring Boot – CrudRepository 示例

Spring Boot – CrudRepository 示例 Spring Boot 建立在 Spring 之上&#xff0c;包含 Spring 的所有功能。由于其快速的生产就绪环境&#xff0c;使开发人员能够直接专注于逻辑&#xff0c;而不必费力配置和设置&#xff0c;因此如今它正成为开发人员的最爱。Spring Boot 是…...

消息队列:原理、问题与设计全解析

1.如何保证消息的顺序性 保证消息顺序性通常是在分布式系统或网络通信中遇到的一个挑战。以下是几种常见的方法来确保消息的顺序性&#xff1a; 单生产者单消费者模型&#xff1a; 如果系统设计为只有一个生产者和一个消费者&#xff0c;那么保持消息顺序相对简单&#xff0c;…...

成功!QT 5.15.2编译mysql驱动

首选要说明&#xff0c;5.15与6.7编译驱动是完全不同的。搞错了永远编译不出来。 参考 主要是参考安装QT&#xff0c;安装mysql等。 编译成功&#xff01;QT/6.7.2/Creator编译Windows64 MySQL驱动(MSVC版)_mingw编译qt6.7-CSDN博客 复制mysql的include和lib到一个方便的目…...

【玩转全栈】----Django连接MySQL

阅前先赞&#xff0c;养好习惯&#xff01; 目录 1、ORM框架介绍 选择建议 2、安装mysqlclient 3、创建数据库 4、修改settings&#xff0c;连接数据库 5、对数据库进行操作 创建表 删除表 添加数据 删除数据 修改&#xff08;更新&#xff09;数据&#xff1a; 获取数据 1、OR…...

【Spring Boot】Spring AOP 快速上手指南:开启面向切面编程新旅程

前言 &#x1f31f;&#x1f31f;本期讲解关于spring aop的入门介绍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不…...

力扣--54.螺旋矩阵

题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 提示&#xff1a; m matrix.length n matrix[i].length 1 < m, n < 10 -100 < matrix[i][j] < 100代码 class Solution { public List spiralOr…...

【Uniapp-Vue3】image媒体组件属性

如果我们想要在页面上展示图片就需要使用到image标签。 这部分最重要的是图片的裁剪&#xff0c;图片的裁剪和缩放属性&#xff1a; mode 图片裁剪、缩放的模式 默认值是scaleToFill 我将用两张图片对属性进行演示&#xff0c;一张是pic1.jpg&#xff08;宽更长&#xf…...

Ubuntu上安装Apache Spark

在Ubuntu上安装Apache Spark的步骤如下&#xff1a; 1. 安装Java Spark是用Scala编写的&#xff0c;并且依赖Java。因此&#xff0c;首先需要安装Java。 安装OpenJDK 8&#xff08;或更高版本&#xff09; 执行以下命令安装OpenJDK&#xff1a; sudo apt update sudo apt …...

Nginx入门笔记

Nginx入门笔记 一、Nginx基本概念二、代理1、正向代理2、反向代理 三、准备工作1、CentOS 7安装nginx&#xff08;1&#xff09;. 安装必要的依赖&#xff08;2&#xff09;下载nginx&#xff08;3&#xff09;编译安装&#xff08;4&#xff09;编译并安装 Nginx(5)启动nginx …...

HTML5 滑动效果(Slide In/Out)详解

HTML5 滑动效果&#xff08;Slide In/Out&#xff09;详解 滑动效果&#xff08;Slide In/Out&#xff09;是一种常见的动画效果&#xff0c;使元素从一侧滑入或滑出&#xff0c;增强页面的动态感和用户体验。以下是滑动效果的详细介绍及实现示例。 1. 滑动效果的特点 动态视…...

unity学习8:unity的基础操作 和对应shortcut

目录 1 unity的基础操作的工具&#xff0c;就在scene边上 1.1 对应shortcut快捷键 2 物体的重置/ 坐标归到0附近 3 F&#xff1a;快速找到当前gameobject 4 Q&#xff1a;小手和眼睛&#xff0c;在场景中移动 5 W&#xff1a;十字箭头&#xff0c;移动gameobject 6 …...

计算机网络 (32)用户数据报协议UDP

前言 用户数据报协议&#xff08;UDP&#xff0c;User Datagram Protocol&#xff09;是计算机网络中的一种重要传输层协议&#xff0c;它提供了无连接的、不可靠的、面向报文的通信服务。 一、基本概念 UDP协议位于传输层&#xff0c;介于应用层和网络层之间。它不像TCP那样提…...

java内存区域 - 栈

目录 java内存区域 - 栈1. Java虚拟机栈的组成2. 栈帧中的详细内容2.1 局部变量表2.2 操作数栈2.3 动态链接2.4 方法返回地址2.5 附加信息 3. JVM栈的生命周期4. 示例解析 - 运行时的栈帧分布5. 栈中的异常6.栈配置7.本地方法栈 java内存区域 - 栈 在JDK11中&#xff0c;JVM栈…...

AI大模型-提示工程学习笔记5

卷首语&#xff1a;我所知的是我自己非常无知&#xff0c;所以我要不断学习。 写给AI入行比较晚的小白们&#xff08;比如我自己&#xff09;看的&#xff0c;大神可以直接路过无视了。 零提示是什么 “零提示”&#xff08;Zero-shot&#xff09;是指在没有提供任何特定示例…...

跨站脚本攻击(XSS)详解

跨站脚本攻击&#xff08;XSS&#xff09;详解 跨站脚本攻击&#xff08;XSS&#xff0c;Cross-Site Scripting&#xff09;是一种通过在网页中注入恶意脚本&#xff0c;攻击用户浏览器的漏洞。攻击者可以利用XSS窃取用户敏感信息、劫持会话、或在受害者浏览器中执行恶意操作。…...

【图像加密解密】Logistic混沌映射的彩色图像加密算法复现(含相关性检验)【Matlab完整源码 1期】

1、说明 本文给出详细完整代码、完整的实验报告和PPT。 环境&#xff1a;MATLAB2019a 复现文献&#xff1a;[1]黄硕.基于改进的Logistic混沌映射彩色图像加密算法[J].河南工程学院学报(自然科学版),2015,27(02):63-67. 主要目的是为了快速了解何为混沌序列、混沌序列产生、…...

VUE学习

import { ref } from vue; 引入了 Vue 的 ref 函数&#xff0c;用于创建响应式数据。const message ref(Hello Vue3); 创建了一个响应式变量 message 并初始化为字符串 Hello Vue3。<h1>{{ message }}</h1> 使用了 Vue 的插值表达式 {{ message }} 来显示 message…...

buildroot 编译 x264 及 ffmpeg

buildroot 编译 x264 及 ffmpeg 依赖安装x264编译安装解压源码并修改配置文件配置及编译编译错误: aarch64-linux-ar: two different operation options specified编译结果ffmpeg安装源码编译错误 : ERROR: x264 not found using pkg-config为在rk3568平台上开发音视频采集及…...

HarmonyOS开发:ArkTS初识

ArkTS基本语法 ArkTS语言简介 ArkTS是鸿蒙生态的应用开发语言。基本语法风格与TypeScript&#xff08;简称TS&#xff09;相似&#xff0c;在TS的生态基础上进一步扩展&#xff0c;继承了TS的所有特性&#xff0c;是TS的超集。 基本语法概述 扩展能力 基础语法&#xff1a…...

C++ STL map和set的使用

序列式容器和关联式容器 想必大家已经接触过一些容器如&#xff1a;list&#xff0c;vector&#xff0c;deque&#xff0c;array&#xff0c;forward_list&#xff0c;string等&#xff0c;这些容器统称为系列容器。因为逻辑结构为线性的&#xff0c;两个位置的存储的值一般是…...

VisionPro软件Image Stitch拼接算法

2D图像拼接的3种情景 1.一只相机取像位置固定&#xff0c;或者多只相机固定位置拍图&#xff0c;硬拷贝拼图&#xff0c;采用CopyRegion工具实现 2.一只或多只相机在多个位置拍照&#xff0c;相机视野互相重叠&#xff0c;基于Patmax特征定位后&#xff0c;无缝 拼图&#xff…...

缓存-Redis-缓存更新策略-主动更新策略-Cache Aside Pattern(全面 易理解)

**Cache-Aside Pattern&#xff08;旁路缓存模式&#xff09;**是一种广泛应用于缓存管理的设计模式&#xff0c;尤其在使用 Redis 作为缓存层时尤为常见。该模式通过在应用程序与缓存之间引入一个旁路&#xff0c;确保数据的一致性和高效性。本文将在之前讨论的 Redis 主动更新…...

Linux(Centos 7.6)命令详解:cd

1.命令作用 改变当前工作目录(change directory) 2.命令语法 Usage: cd [-L|[-P [-e]]] [dir] 3.参数详解 -L‌&#xff0c;当目标路径是符号链接时&#xff0c;强制使用符号链接&#xff0c;这是一个默认选项。-P‌&#xff0c;使用物理路径代替符号链接。-e‌&#xff0…...

oracle位运算、左移右移、标签算法等

文章目录 位运算基础与或非同或同或应用场景 异或异或应用场景 什么是真值表 oracle基础函数创建bitor(按位或)函数bitnot(按位非)函数bitxor(按位异或)函数左移函数BITSHIFT()函数(实测不可用&#xff0c;废弃掉该方案)右移函数(略&#xff0c;有此场景吗?) 实际应用资质字典…...

预训练语言模型——BERT

1.预训练思想 有了预训练就相当于模型在培养大学生做任务&#xff0c;不然模型初始化再做任务就像培养小学生 当前数据层面的瓶颈是能用于预训练的语料快被用完了 现在有一个重要方向是让机器自己来生成数据并做微调 1.1 预训练&#xff08;Pre - training&#xff09;vs. 传…...

基于Thinkphp6+uniapp的陪玩陪聊软件开发方案分析

使用uni-app框架进行前端开发。uni-app是一个使用Vue.js开发所有前端应用的框架&#xff0c;支持一次编写&#xff0c;多端发布&#xff0c;包括APP、小程序、H5等。 使用Thinkphp6框架进行后端开发。Thinkphp6是一个轻量级、高性能、面向对象的PHP开发框架&#xff0c;具有易…...

C++异常处理

C异常处理 C中的异常处理机制是通过try、throw和catch三个关键字来实现的&#xff0c;主要用于捕获和处理程序执行过程中可能出现的错误或异常情况&#xff0c;从而提高程序的健壮性和可维护性。 基本概念 try块&#xff1a;用于定义一个可能抛出异常的代码块。在这个代码块…...

UVM: TLM机制

topic overview 不建议的方法&#xff1a;假如没有TLM TLM TLM 1.0 整个TLM机制下&#xff0c;底层逻辑离不开动作发起者和被动接受者这个底层的模型基础&#xff0c;但实际上&#xff0c;在验证环境中&#xff0c;任何一个组件&#xff0c;都有可能成为动作的发起者&#xff0…...