99. UE5 GAS RPG 被动技能实现
在这一篇,我们在之前打下的基础下,实现一下被动技能。
被动技能需要我们在技能栏上面选择升级解锁技能后,将其设置到技能栏,我们先增加被动技能使用的标签。
FGameplayTag Abilities_Passive_HaloOfProtection; //被动技能-守护光环FGameplayTag Abilities_Passive_LifeSiphon; //被动技能-生命回复FGameplayTag Abilities_Passive_ManaSiphon; //被动技能-蓝量回复
注册一下
/** 被动技能*/GameplayTags.Abilities_Passive_HaloOfProtection = UGameplayTagsManager::Get().AddNativeGameplayTag(FName("Abilities.Passive.HaloOfProtection"),FString("守护光环"));GameplayTags.Abilities_Passive_LifeSiphon = UGameplayTagsManager::Get().AddNativeGameplayTag(FName("Abilities.Passive.LifeSiphon"),FString("生命自动回复"));GameplayTags.Abilities_Passive_ManaSiphon = UGameplayTagsManager::Get().AddNativeGameplayTag(FName("Abilities.Passive.ManaSiphon"),FString("蓝量自动回复"));
添加被动技能基类
我们基于技能基类创建一个派生类,用于作为被动技能的基类
命名为RPGPassiveAbility
在类里增加两个函数,一个是覆写激活技能函数,在技能被调用激活时,绑定结束回调监听,如果ASC调用了结束技能,并且此被动技能刚好有对应的标签,我们可以通过第二个技能结束此技能实力的激活。
public:/*** 覆写激活技能函数* @param Handle 技能实力的句柄* @param ActorInfo 技能拥有者* @param ActivationInfo 激活信息* @param TriggerEventData 游戏事件信息*/virtual void ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData) override;/*** 接收到技能结束回调函数* @param AbilityTag 结束的技能标识标签*/void ReceiveDeactivate(const FGameplayTag& AbilityTag);
我们在ASC里增加一个新的委托定义,用来定义技能结束
DECLARE_MULTICAST_DELEGATE_OneParam(FDeactivatePassiveAbility, const FGameplayTag& /*技能标签*/); //中止一个技能激活的回调
并在ASC类里新增一个变量
FDeactivatePassiveAbility DeactivatePassiveAbility; //取消技能激活的委托
在被动技能基类里,激活技能时,绑定委托的监听
void URPGPassiveAbility::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{Super::ActivateAbility(Handle, ActorInfo, ActivationInfo, TriggerEventData);//获取到ASCif(URPGAbilitySystemComponent* RPGASC = Cast<URPGAbilitySystemComponent>(UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetAvatarActorFromActorInfo()))){//绑定技能取消回调RPGASC->DeactivatePassiveAbility.AddUObject(this, &URPGPassiveAbility::ReceiveDeactivate);}
}
在回调里,判断委托返回的标签是否为当前被动技能的标识,如果是,将调用结束技能
void URPGPassiveAbility::ReceiveDeactivate(const FGameplayTag& AbilityTag)
{//判断技能标签容器里是否包含此标签if(AbilityTags.HasTagExact(AbilityTag)){EndAbility(CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, true, true);}
}
创建对应被动技能蓝图
有了被动技能基类,我们在UE里创建对应的蓝图
基于之前创建的基类创建三个被动技能
在技能标识标签这里设置对应的标签
然后在DA_AbilityInfo里添加对应的技能的相关数据
接下来,我们在UI里实现设置按钮显示哪个技能标签
接着运行,查看按钮是否能够正确显示以及操作
记得在主窗口的UI上设置对应的按钮Tag
运行设置后查看,是否主界面也能够跟随变动
实现被动技能的装配时激活
技能可以实现了装配,并且,我们在技能里监听了取消事件,在触发对应回调时,技能会自动取消激活。
所以,我们在被动技能里设置调试节点,方便测试,在激活时和结束技能时都可以打印信息。
由于被动技能应用时就需要激活,所以,我们不需要预测它,直接在服务器初始化即可。
这是我们现在的ASC里装配技能时的处理逻辑,没有考虑到主动技能和被动技能的区别
接下来,我们将修改技能装配的逻辑,让其兼容对被动技能的处理。
前面的这一段还是一样,通过技能标签获取到技能实例,并获取到技能未修改前装配的槽位和状态,对技能的状态进行判断
void URPGAbilitySystemComponent::ServerEquipAbility_Implementation(const FGameplayTag& AbilityTag, const FGameplayTag& Slot)
{const FRPGGameplayTags GameplayTags = FRPGGameplayTags::Get();//获取到技能实例if(FGameplayAbilitySpec* AbilitySpec = GetSpecFromAbilityTag(AbilityTag)){const FGameplayTag& PrevSlot = GetInputTagFromSpec(*AbilitySpec); //技能之前装配的插槽const FGameplayTag& Status = GetStatusTagFromSpec(*AbilitySpec); //当前技能的状态标签//判断技能的状态,技能状态只有在已装配或者已解锁的状态才可以装配if(Status == GameplayTags.Abilities_Status_Equipped || Status == GameplayTags.Abilities_Status_Unlocked){
接着,我们先处理目标槽位,判断目标槽位现在是否装配技能,如果装配,我们则获取到装配的技能实例,如果槽位装配的技能和我们需要装配的技能相同,则不做处理。
如果槽位的技能是被动技能,我们将通过委托结束技能(被动技能基类在激活技能时,会监听技能结束委托)
并且,我们将会清除槽位所有装配的技能(清除装配技能上设置的输入标签)
//判断插槽是否有技能,有则需要将其清除
if(!SlotIsEmpty(Slot))
{//获取目标插槽现在装配的技能if(const FGameplayAbilitySpec* SpecWithSlot = GetSpecWithSlot(Slot)){//技能槽位装配相同的技能,直接返回,不做额外的处理if(AbilityTag.MatchesTagExact(GetAbilityTagFromSpec(*SpecWithSlot))){ClientEquipAbility(AbilityTag, Status, Slot, PrevSlot);return;}//如果是被动技能,我们需要先将技能取消执行if(IsPassiveAbility(*SpecWithSlot)){DeactivatePassiveAbility.Broadcast(GetAbilityTagFromSpec(*SpecWithSlot));}ClearAbilitiesOfSlot(Slot); //清除目标插槽装配的技能}
}
接下来,我们对需要装配的技能判断,如果它之前没有被装配到技能槽位,并且还是被动技能,证明技能还未被激活,我们需要将技能激活。
//技能没有设置到插槽(没有激活)
if(!AbilityHasAnySlot(*AbilitySpec))
{//如果是被动技能,装配即激活if(IsPassiveAbility(*AbilitySpec)){TryActivateAbility(AbilitySpec->Handle);}
}
然后修改技能的的输入标签为装配的槽位
//修改技能装配的插槽
AssignSlotToAbility(*AbilitySpec, Slot);
最后网络同步和触发装配委托回调
//回调更新UI
ClientEquipAbility(AbilityTag, Status, Slot, PrevSlot);
MarkAbilitySpecDirty(*AbilitySpec); //立即将其复制到每个客户端
逻辑梳理完成,下面为使用到的一些函数
bool URPGAbilitySystemComponent::SlotIsEmpty(const FGameplayTag& Slot)
{FScopedAbilityListLock ActiveScopeLoc(*this);for(FGameplayAbilitySpec& AbilitySpec : GetActivatableAbilities()){if(AbilityHasSlot(AbilitySpec, Slot)){return false;}}return true;
}bool URPGAbilitySystemComponent::AbilityHasSlot(const FGameplayAbilitySpec& Spec, const FGameplayTag& Slot)
{return Spec.DynamicAbilityTags.HasTagExact(Slot);
}bool URPGAbilitySystemComponent::AbilityHasAnySlot(const FGameplayAbilitySpec& Spec)
{//通过判断动态标签是否含有Input的标签来判断技能是否装配到槽位return Spec.DynamicAbilityTags.HasTag(FGameplayTag::RequestGameplayTag(FName("InputTag")));
}FGameplayAbilitySpec* URPGAbilitySystemComponent::GetSpecWithSlot(const FGameplayTag& Slot)
{FScopedAbilityListLock ActiveScopeLoc(*this);for(FGameplayAbilitySpec& AbilitySpec : GetActivatableAbilities()){if(AbilityHasSlot(AbilitySpec, Slot)){return &AbilitySpec;}}return nullptr;
}bool URPGAbilitySystemComponent::IsPassiveAbility(const FGameplayAbilitySpec& Spec) const
{//从技能配置数据里获取到技能对于的配置信息UAbilityInfo* AbilityInfo = URPGAbilitySystemLibrary::GetAbilityInfo(GetAvatarActor());const FGameplayTag AbilityTag = GetAbilityTagFromSpec(Spec);const FRPGAbilityInfo& Info = AbilityInfo->FindAbilityInfoForTag(AbilityTag);//判断信息里配置的技能类型是否为被动技能const FGameplayTag AbilityType = Info.AbilityType;return AbilityType.MatchesTagExact(FRPGGameplayTags::Get().Abilities_Type_Passive);
}void URPGAbilitySystemComponent::AssignSlotToAbility(FGameplayAbilitySpec& Spec, const FGameplayTag& Slot)
{const FRPGGameplayTags GameplayTags = FRPGGameplayTags::Get();ClearSlot(&Spec);Spec.DynamicAbilityTags.AddTag(Slot);Spec.DynamicAbilityTags.RemoveTag(GameplayTags.Abilities_Status_Unlocked);Spec.DynamicAbilityTags.AddTag(GameplayTags.Abilities_Status_Equipped);
}
void URPGAbilitySystemComponent::ClearSlot(FGameplayAbilitySpec* Spec)
{const FGameplayTag Slot = GetInputTagFromSpec(*Spec);Spec->DynamicAbilityTags.RemoveTag(Slot);// MarkAbilitySpecDirty(*Spec);
}void URPGAbilitySystemComponent::ClearAbilitiesOfSlot(const FGameplayTag& Slot)
{FScopedAbilityListLock ActiveScopeLock(*this);for(FGameplayAbilitySpec& Spec : GetActivatableAbilities()){if(AbilityHasSlot(&Spec, Slot)){ClearSlot(&Spec);}}
}
最后展示一下实现装配的所有代码
void URPGAbilitySystemComponent::ServerEquipAbility_Implementation(const FGameplayTag& AbilityTag, const FGameplayTag& Slot)
{const FRPGGameplayTags GameplayTags = FRPGGameplayTags::Get();//获取到技能实例if(FGameplayAbilitySpec* AbilitySpec = GetSpecFromAbilityTag(AbilityTag)){const FGameplayTag& PrevSlot = GetInputTagFromSpec(*AbilitySpec); //技能之前装配的插槽const FGameplayTag& Status = GetStatusTagFromSpec(*AbilitySpec); //当前技能的状态标签//判断技能的状态,技能状态只有在已装配或者已解锁的状态才可以装配if(Status == GameplayTags.Abilities_Status_Equipped || Status == GameplayTags.Abilities_Status_Unlocked){//判断插槽是否有技能,有则需要将其清除if(!SlotIsEmpty(Slot)){//获取目标插槽现在装配的技能if(const FGameplayAbilitySpec* SpecWithSlot = GetSpecWithSlot(Slot)){//技能槽位装配相同的技能,直接返回,不做额外的处理if(AbilityTag.MatchesTagExact(GetAbilityTagFromSpec(*SpecWithSlot))){ClientEquipAbility(AbilityTag, Status, Slot, PrevSlot);return;}//如果是被动技能,我们需要先将技能取消执行if(IsPassiveAbility(*SpecWithSlot)){DeactivatePassiveAbility.Broadcast(GetAbilityTagFromSpec(*SpecWithSlot));}ClearAbilitiesOfSlot(Slot); //清除目标插槽装配的技能}}//技能没有设置到插槽(没有激活)if(!AbilityHasAnySlot(*AbilitySpec)){//如果是被动技能,装配即激活if(IsPassiveAbility(*AbilitySpec)){TryActivateAbility(AbilitySpec->Handle);}}//修改技能装配的插槽AssignSlotToAbility(*AbilitySpec, Slot);//回调更新UIClientEquipAbility(AbilityTag, Status, Slot, PrevSlot);MarkAbilitySpecDirty(*AbilitySpec); //立即将其复制到每个客户端}}
}
运行查看装配后,对应的打印是否能够正常打印。
添加被动技能表现特效
现在技能可以激活了,我们需要让玩家能够知道被动技能生效的效果,参照之前的debuff应用,我们将参照之前的方式实现,即使出现了问题,那是一种比较好的解耦方式。
首先,我们创建一个被动技能表现基类
命名为PassiveNiagaraComponent
在基类里,我们需要一个设置标签,用于启动时对应的被动技能标签,然后添加一个监听回调的函数。
UCLASS()
class RPG_API UPassiveNiagaraComponent : public UNiagaraComponent
{GENERATED_BODY()public:UPassiveNiagaraComponent();//激活此被动技能特效的技能标签UPROPERTY(EditDefaultsOnly)FGameplayTag PassiveSpellTag;protected:virtual void BeginPlay() override;/*** 监听技能变动后的委托回调,用于设置此实例是否需要激活* @param AbilityTag 对应的技能的标签* @param bActivate 激活还是关闭*/void OnPassiveActivate(const FGameplayTag& AbilityTag, bool bActivate);
};
在构造函数里,将特效自动激活关闭
在事件开始时,绑定ASC里被动技能应用委托,通过监听被动技能应用委托来触发回调
在回调里,判断标签是否对应,根据需要开启和关闭设置特效组件的开启关闭。
UPassiveNiagaraComponent::UPassiveNiagaraComponent()
{bAutoActivate = false;
}void UPassiveNiagaraComponent::BeginPlay()
{Super::BeginPlay();if(URPGAbilitySystemComponent* RPGASC = Cast<URPGAbilitySystemComponent>(UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetOwner()))){RPGASC->ActivatePassiveEffect.AddUObject(this, &UPassiveNiagaraComponent::OnPassiveActivate);}else if(ICombatInterface* CombatInterface = Cast<ICombatInterface>(GetOwner())){//AddWeakLambda 这种绑定方式的主要好处是,当绑定的对象被销毁时,委托不会保持对象的引用,从而避免悬空指针问题和内存泄漏。CombatInterface->GetOnASCRegisteredDelegate().AddWeakLambda(this,[this](UAbilitySystemComponent* InASC){if(URPGAbilitySystemComponent* RPGASC = Cast<URPGAbilitySystemComponent>(InASC)){RPGASC->ActivatePassiveEffect.AddUObject(this, &UPassiveNiagaraComponent::OnPassiveActivate);}});}
}void UPassiveNiagaraComponent::OnPassiveActivate(const FGameplayTag& AbilityTag, bool bActivate)
{//判断技能标签是否一致if(AbilityTag.MatchesTagExact(PassiveSpellTag)){//判断是否需要激活if(bActivate){//不需要重复激活if(!IsActive()) Activate();}else{Deactivate();}}
}
在ASC类里,我们增加一个新的委托类型
DECLARE_MULTICAST_DELEGATE_TwoParams(FActivePassiveEffect, const FGameplayTag& /*被动技能标签*/, bool /*激活或取消*/); //被动技能特效监听委托,对应特效是否开启
在ASC类里新增一个对应类型的属性
FActivePassiveEffect ActivatePassiveEffect; //被动技能对应特效委托
增加一个多播函数,它会在每个客户端和服务器运行,保证都能够查看到对应效果,设置Unreliable,用来设置它不是重要的,不需要优先同步
/*** 多网络被动特效委托广播,让每个客户端都可以看到特效* @param AbilityTag 被动技能标签* @param bActivate 激活或者关闭*/UFUNCTION(NetMulticast, Unreliable)void MulticastActivatePassiveEffect(const FGameplayTag& AbilityTag, bool bActivate);
然后在函数里调用委托,让每个客户端对应的ASC都会调用此函数
void URPGAbilitySystemComponent::MulticastActivatePassiveEffect_Implementation(const FGameplayTag& AbilityTag, bool bActivate)
{ActivatePassiveEffect.Broadcast(AbilityTag, bActivate);
}
然后在我们装配技能时,取消被动执行时,调用它传入false
在激活一个被动技能时,我们设置对应的特效激活
最后,就是在角色类里,我们需要对应的特效组件,对每一种特效都创建一个对应的特效
//光环被动技能特效组件UPROPERTY(VisibleAnywhere)TObjectPtr<UPassiveNiagaraComponent> HaloOfProtectionNiagaraComponent;//回血被动技能特效组件UPROPERTY(VisibleAnywhere)TObjectPtr<UPassiveNiagaraComponent> LifeSiphonNiagaraComponent;//回蓝被动技能特效组件UPROPERTY(VisibleAnywhere)TObjectPtr<UPassiveNiagaraComponent> ManaSiphonNiagaraComponent;//被动技能挂载的组件UPROPERTY(VisibleAnywhere)TObjectPtr<USceneComponent> EffectAttachComponent;
然后在构造函数里创建实例,并挂载到特效根组件,我们创建特效根组件的原因是为了保证特效不会跟随角色旋转
//实例化被动技能组件,并挂载EffectAttachComponent = CreateDefaultSubobject<USceneComponent>("EffectAttachPoint");EffectAttachComponent->SetupAttachment(GetRootComponent());HaloOfProtectionNiagaraComponent = CreateDefaultSubobject<UPassiveNiagaraComponent>("HaloOfProtectionComponent");HaloOfProtectionNiagaraComponent->SetupAttachment(EffectAttachComponent);LifeSiphonNiagaraComponent = CreateDefaultSubobject<UPassiveNiagaraComponent>("LifeSiphonComponent");LifeSiphonNiagaraComponent->SetupAttachment(EffectAttachComponent);ManaSiphonNiagaraComponent = CreateDefaultSubobject<UPassiveNiagaraComponent>("ManaSiphonComponent");ManaSiphonNiagaraComponent->SetupAttachment(EffectAttachComponent);
我们需要在帧更新里去修改特效根组件的旋转,让其保证相对于世界不会旋转,所以需要覆写帧更新函数
virtual void Tick(float DeltaSeconds) override;
在帧更新函数里,我们每一帧都将其旋转值设置为相对于世界坐标默认为0
void ARPGCharacterBase::Tick(float DeltaSeconds)
{Super::Tick(DeltaSeconds);//防止特效跟随人物旋转,每一帧更新修改旋转为默认EffectAttachComponent->SetWorldRotation(FRotator::ZeroRotator);
}
之前我们没有使用帧更新,它是关掉的,现在我们需要将其开启
// 将这个字符设置为true时,将每帧进行更新。不需要可以关闭提高性能。PrimaryActorTick.bCanEverTick = true;
接下来,我们编译打开蓝图,查看玩家角色蓝图是否生成了对应的组件
我们为每个特效组件设置对应的资产
并设置特效组件对应的被动技能,这样,在被动技能被应用时,特效也将会激活。
接下来就是运行查看效果。
实现被动技能效果
在前面,被动技能可以触发对应技能里的激活和结束回调节点,我们可以以此为出发点,来给玩家角色应用GE。
我们创建一个基础的被动技能蓝图,将一些公共的配置和函数在此函数完成
在蓝图里,我们添加一个设置GE类的变量
增加一个添加GE给自身的函数
再增加一个通过类删除GE的函数
默认激活技能时,调用添加函数,技能结束时删除GE
接着,我们增加一个新的GE类
这里我先做一个蓝量回复的类,类型设置为时间无限,每一秒执行一次
在Modifiers里,我们增加一个属性修改,属性基于之前设置的蓝量回复的值
在被动技能里,我们将被动技能基类修改为创建的蓝图基类
事件调用修改为调用父节点
父节点可以通过右键查找到添加
最后修改GE的默认值的类
在我们应用了被动技能后,你会发现蓝量在慢慢回复,并且是每一秒回复一次。
被动技能这里只是给大家一个实现思路,大家可以实现更多的被动技能。
相关文章:

99. UE5 GAS RPG 被动技能实现
在这一篇,我们在之前打下的基础下,实现一下被动技能。 被动技能需要我们在技能栏上面选择升级解锁技能后,将其设置到技能栏,我们先增加被动技能使用的标签。 FGameplayTag Abilities_Passive_HaloOfProtection; //被动技能-守护光…...

U盘装系统,使用U盘启动,提示需要装驱动
今天装win10系统,用的是U盘启动,但安装过程中出现了找不到驱动程序无法完成安装的问题,逛了许多的论坛,换过两三个iso文件都不顶用,使用了许多种方式,都安装失败,最后在某个论坛看到一种安装方式…...

gaussdb 主备 8 数据库安全学习
1 用户及权限 1.1 默认权限机制-未开启三权分立 1.1.1 数据库系统管理员具有与对象所有者相同的权限。也就是说对象创建后,默认只有对象所有者或者系统管理员可以查询、修改和销毁对象,以及通过GRANT将对象的权限授予其他用户。 1.1.2 GaussDB支持以下的…...
React 基础阶段学习计划
React 基础阶段学习计划 目标 能够创建和使用React组件。理解并使用State和Props。掌握事件处理和表单处理。 学习内容 环境搭建 安装Node.js和npm 访问 Node.js官网 下载并安装最新版本的Node.js。打开终端或命令行工具,输入 node -v 和 npm -v 检查是否安装…...

FFmpeg的简单使用【Windows】--- 指定视频的时长
目录 功能描述 效果展示 代码实现 前端代码 后端代码 routers 》users.js routers 》 index.js app.js 功能描述 此案例是在上一个案例【FFmpeg的简单使用【Windows】--- 视频混剪添加背景音乐-CSDN博客】的基础上的进一步完善,可以先去看上一个案例然后再…...

请求参数中字符串的+变成了空格
前端请求 后端接收到的结果 在URL中,某些字符(包括空格、、&、? 等)需要被编码。具体而言,在URL中,空格通常被编码为 或 %20。因此,如果你在请求参数中使用 ,它会被解释为一个空格。 如果…...

前端开发攻略---使用AJAX监控网络请求进度
1、XHR实现 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Document</title></head&…...

[已解决]DockerTarBuilder永久解决镜像docker拉取异常问题
前阵子发现阿里云的docker加速镜像失效了(甚至连nginx都拉取不了),重新换了并且加多了网络上比较常用的dokcer加速源,可以解决一部分问题,但仍然有一些镜像的某个版本或一些比较冷的镜像就是拉取不了,原因未…...

机器学习实战27-基于双向长短期记忆网络 BiLSTM 的黄金价格模型研究
大家好,我是微学AI,今天给大家介绍一下机器学习实战27-基于双向长短期记忆网络 BiLSTM 的黄金价格模型研究。本文针对黄金价格预测问题,展开基于改造后的长短期记忆网络BiLSTM的黄金价格模型研究。文章首先介绍了项目背景,随后详细…...

阿拉伯应用市场的特点
阿拉伯应用程序市场是一个充满活力和快速增长的行业,由年轻、精通技术的人口、高智能手机渗透率和整个地区数字化程度的提高所塑造。作为世界上最大的消费群体之一,阿拉伯语受众为希望扩大影响力的开发商和品牌提供了巨大的潜力。 文化相关性在应用程序…...

音频响度归一化 - python 实现
在处理音频样本时,往往我们的音频样本由于录制设备,环境,人发音的音量大小的不同影响,会造成音频响度不统一,分布在一个不同的响度值域上。为了让语音模型更好的学习音频特征,就有必要对音频的响度进行归一…...
嵌入式硬件设计详解
嵌入式硬件设计详解 嵌入式硬件设计是一个复杂而精细的过程,它涉及将微控制器(MCU)、微处理器(MPU)或数字信号处理器(DSP)等核心芯片与其他外围电子元件(如传感器、执行器、存储器、…...
Linux防火墙与SElinux
文章目录 一、防火墙介绍二、iptables和firewalld的区别操作方式:配置层面:性能和管理: 三、iptables与firewalld的优缺点iptablesfirewalld 四、iptables的工作流程五、firewalld的工作流程六、iptables安装与使用6.1、关闭firewalld服务6.2…...

【MySQL】基本查询(上):创建、读取
1.Create(创建) 语法: INSERT [INTO] table_name [(column [, column] ...)] VALUES (value_list) [, (value_list)] ...value_list: value, [, value] ... 接下来我们用这个下表作为例子: -- 创建一张学生表 CREATE TABLE students ( id INT UNSIGN…...

在线刷题系统测试报告
一、项目背景 1. 本项目是一个在线刷题系统,灵感来源于力扣和牛客等刷题平台,旨在锻炼自己的代码能力和剖析系统整体结构与各模块之间关系的能力。系统支持用户注册与登录,查看题目列表与题目详情,在线提交代码并提供反馈。 2. 该…...

即时通讯增加Redis渠道
情况说明 在本地和服务器分别启动im服务,当本地发送消息时,会发现服务器上并没有收到消息 初版im只支持单机版,不支持分布式的情况。此次针对该情况对项目进行优化,文档中贴出的代码非完整代码,可自行查看参考资料[2] 代码结构调…...

C++list
list简介 list是我们的链表,而且是带头双向循环链表,如下图 我们都知道,链表是由一个一个的节点组成的,它的成员由下面几个部分组成 通过对前面string,vector的学习,其实再来看我们的链表及其成员函数,是…...
设计模式 - 结构型
结构型 适配器模式,代理模式,桥接模式,装饰器模式,外观模式,组合模式,享元模式, 单一职责避免子类爆炸Bridge 模式对象的实现Decorator 模式对对象的职责,不生成子类接口隔离Adapt…...

STM32编码器接口
一、概述 1、Encoder Interface 编码器接口概念 编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度每个高级定时器和通用…...

2024客户世界年度大会开幕,码号卫士赋能数字运营服务新升级
10月15日,2024年客户世界年度的大会在通州北投希尔顿酒店开幕。作为行业内的一个重要活动,本次大会以“数字运营支撑服务产业新升级”为主题,吸引了众多行业专家和企业代表。 据悉,本次大会以“数字运营支撑服务产业新升级”为主题…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...

消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
python打卡第47天
昨天代码中注意力热图的部分顺移至今天 知识点回顾: 热力图 作业:对比不同卷积层热图可视化的结果 def visualize_attention_map(model, test_loader, device, class_names, num_samples3):"""可视化模型的注意力热力图,展示模…...
嵌入式面试常问问题
以下内容面向嵌入式/系统方向的初学者与面试备考者,全面梳理了以下几大板块,并在每个板块末尾列出常见的面试问答思路,帮助你既能夯实基础,又能应对面试挑战。 一、TCP/IP 协议 1.1 TCP/IP 五层模型概述 链路层(Link Layer) 包括网卡驱动、以太网、Wi‑Fi、PPP 等。负责…...

【阅读笔记】MemOS: 大语言模型内存增强生成操作系统
核心速览 研究背景 研究问题:这篇文章要解决的问题是当前大型语言模型(LLMs)在处理内存方面的局限性。LLMs虽然在语言感知和生成方面表现出色,但缺乏统一的、结构化的内存架构。现有的方法如检索增强生成(RA…...

python基础语法Ⅰ
python基础语法Ⅰ 常量和表达式变量是什么变量的语法1.定义变量使用变量 变量的类型1.整数2.浮点数(小数)3.字符串4.布尔5.其他 动态类型特征注释注释是什么注释的语法1.行注释2.文档字符串 注释的规范 常量和表达式 我们可以把python当作一个计算器,来进行一些算术…...