在上一篇文章里,我们实现了添加负面效果GE,并且在添加GE时,也会给脚色应用一个负面效果标签作为标识。在这一篇里,我们将通过负面效果标签标识,应用脚色身上展现对应的负面效果的表现。
我们将在这篇文章里添加一个自界说的Niagara组件,来实现对应的负面效果表现,并通过观察脚色身上是否应用的对应的标签,来激活和取消激活组件。
解决应用标签的bug
起首我们解决之前编写的通过代码设置GE标签的方法。
和之前的相比,有两处标题,第一处就是不应该直接获取,而是直接创建一个新的FInheritedTagContainer。
第二处是在添加的地方需要设置到Added对象上,对应UE里设置GE。
- UTargetTagsGameplayEffectComponent& TargetTagsGameplayEffectComponent = Effect->AddComponent<UTargetTagsGameplayEffectComponent>();
- FInheritedTagContainer InheritableOwnedTagsContainer; //创建组件所需的标签容器
- InheritableOwnedTagsContainer.Added.AddTag(DeBuffType); //添加标签
- TargetTagsGameplayEffectComponent.SetAndApplyTargetTagChanges(InheritableOwnedTagsContainer); //应用并更新
复制代码 创建自界说的Niagara组件类
为了可以大概自界说负面效果表现的主动开关功能,我们需要自己扩展Niagara类,在内里增加内容。
我们基于NiagaraComponent创建一个派生类
设定好相干名称和目次
在派生类里,我们添加构造函数,设置标识当前对应的负面效果的标签,以及对应标签变动回调以及脚色死亡回调。
- UCLASS()
- class RPG_API UDeBuffNiagaraComponent : public UNiagaraComponent
- {
- GENERATED_BODY()
- public:
- UDeBuffNiagaraComponent();
-
- UPROPERTY(EditDefaultsOnly)
- FGameplayTag DeBuffTag; //用来标识粒子系统的标签
- protected:
- virtual void BeginPlay() override; //覆写开始运行
- void DeBuffTagChanged(const FGameplayTag CallbackTag, int32 NewCount); //当前的负面标签变动回调
- UFUNCTION()
- void OnOwnerDeath(AActor* DeadActor); //在角色死亡时的回调
- };
复制代码 在构造函数中,我们将主动激活关闭
- UDeBuffNiagaraComponent::UDeBuffNiagaraComponent()
- {
- bAutoActivate = false; //关闭自动激活
- }
复制代码 在事件开始执行时,我们绑定对应的回调,用来检测脚色的变动,并在变动时触发回调
- void UDeBuffNiagaraComponent::BeginPlay()
- {
- Super::BeginPlay();
- ICombatInterface* CombatInterface = Cast<ICombatInterface>(GetOwner()); //获取到战斗接口
- //通过函数库获取角色身上的ASC
- if(UAbilitySystemComponent* ASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetOwner()))
- {
- //监听负面标签变动回调
- ASC->RegisterGameplayTagEvent(DeBuffTag, EGameplayTagEventType::NewOrRemoved).AddUObject(this, &UDeBuffNiagaraComponent::DeBuffTagChanged);
- }
- else if(CombatInterface) //如果绑定时,ASC未初始化成功,则监听ASC创建完成委托,完成对负面标签的监听
- {
- //AddWeakLambda 这种绑定方式的主要好处是,当绑定的对象被销毁时,委托不会保持对象的引用,从而避免悬空指针问题和内存泄漏。
- CombatInterface->GetOnASCRegisteredDelegate().AddWeakLambda(this,[this](UAbilitySystemComponent* InASC)
- {
- //监听负面标签变动回调
- InASC->RegisterGameplayTagEvent(DeBuffTag, EGameplayTagEventType::NewOrRemoved).AddUObject(this, &UDeBuffNiagaraComponent::DeBuffTagChanged);
- });
- }
- //绑定死亡后销毁
- if(CombatInterface)
- {
- CombatInterface->GetOnDeathDelegate().AddDynamic(this, &UDeBuffNiagaraComponent::OnOwnerDeath);
- }
- }
复制代码 监听负面效果标签的回调里,我们可以获取脚色身上对应标签的个数,假如不为0,则激活粒子
- void UDeBuffNiagaraComponent::DeBuffTagChanged(const FGameplayTag CallbackTag, int32 NewCount)
- {
- if(NewCount > 0)
- {
- Activate(); //绑定的负面标签大于0,激活特效
- }
- else
- {
- Deactivate(); //没有对应标签,关闭激活
- }
- }
复制代码 在触发死亡回调时,关闭激活
- void UDeBuffNiagaraComponent::OnOwnerDeath(AActor* DeadActor)
- {
- Deactivate();
- }
复制代码 添加对应委托
在自界说Niagara组件里,我们需要两个委托来监听脚色身上的负面标签变动以及脚色是否死亡
在战斗接口类里,我们增加两个委托,可以通过其举行绑定
Dynamic的区别在于能不能绑定蓝图,非Dynamic的无法绑定,Dynamic的需要通过UE反射绑定,也可以直接蓝图获取绑定。
- DECLARE_MULTICAST_DELEGATE_OneParam(FOnASCRegistered, UAbilitySystemComponent*); //Actor初始化ASC完成后委托
- DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnDeath, AActor*, DeadActor); //Actor死亡后的委托
复制代码 然后我们在类里增加两个获取函数,可以获取对应的委托,这里我们需要返回引用
- virtual FOnASCRegistered& GetOnASCRegisteredDelegate() = 0; //获取ASC注册成功后的委托
- virtual FOnDeath& GetOnDeathDelegate() = 0; //获取死亡委托
复制代码 接着,我们在脚色基类里增加两个对应的委托
- FOnASCRegistered OnASCRegistered; //ASC注册成功委托
- FOnDeath OnDeath; //角色死亡后触发的死亡委托
复制代码 覆写两个函数
- virtual FOnASCRegistered& GetOnASCRegisteredDelegate() override; //获取ASC注册成功委托
- virtual FOnDeath& GetOnDeathDelegate() override; //角色死亡委托
复制代码 对实在现一下,返回对应的委托
- FOnASCRegistered& ARPGCharacter::GetOnASCRegisteredDelegate()
- {
- return OnASCRegistered;
- }
- FOnDeath& ARPGCharacter::GetOnDeathDelegate()
- {
- return OnDeath;
- }
复制代码 触发委托
现在我们创建完成了对应的委托,还需要在符合的位置对其举行广播
起首是ASC创建完成后的广播,我选择在InitAbilityActorInfo函数里,创建完成ASC后广播
- void ARPGEnemy::InitAbilityActorInfo()
- {
- AbilitySystemComponent->InitAbilityActorInfo(this, this);
- Cast<URPGAbilitySystemComponent>(AbilitySystemComponent)->AbilityActorInfoSet();
- //通过GE初始角色的属性
- if(HasAuthority())
- {
- InitializeDefaultAttributes();
- }
- //调用ASC广播
- OnASCRegistered.Broadcast(AbilitySystemComponent);
- }
复制代码 脚色的函数内容不同,在函数执行完时,也完成了广播
- void ARPGHero::InitAbilityActorInfo()
- {
- ARPGPlayerState* PlayerStateBase = GetPlayerState<ARPGPlayerState>();
- check(PlayerStateBase); //检测是否有效,无限会暂停游戏
- //从playerState获取ASC和AS
- AbilitySystemComponent = PlayerStateBase->GetAbilitySystemComponent();
- AttributeSet = PlayerStateBase->GetAttributeSet();
- //初始化ASC
- AbilitySystemComponent->InitAbilityActorInfo(PlayerStateBase, this);
- //触发Actor的技能信息设置回调
- Cast<URPGAbilitySystemComponent>(AbilitySystemComponent)->AbilityActorInfoSet();
- //获取PC
- if(ARPGPlayerController* PlayerControllerBase = Cast<ARPGPlayerController>(GetController()))
- {
- if(ARPGHUD* HUD = Cast<ARPGHUD>(PlayerControllerBase->GetHUD()))
- {
- HUD->InitOverlay(PlayerControllerBase, PlayerStateBase, AbilitySystemComponent, AttributeSet);
- }
- }
- //通过GE初始角色的属性
- InitializeDefaultAttributes();
- //调用ASC广播
- OnASCRegistered.Broadcast(AbilitySystemComponent);
- }
复制代码 然后就是脚色的死亡委托广播,我们之前创建了一个多播函数,在脚色死亡后,每个游戏端都会触发此函数
- void ARPGCharacter::MulticastHandleDeath_Implementation()
- {
- //播放死亡音效
- UGameplayStatics::PlaySoundAtLocation(this, DeathSound, GetActorLocation());
-
- //开启武器物理效果
- Weapon->SetSimulatePhysics(true); //开启模拟物理效果
- Weapon->SetEnableGravity(true); //开启重力效果
- Weapon->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly); //开启物理碰撞通道
- //开启角色物理效果
- GetMesh()->SetSimulatePhysics(true); //开启模拟物理效果
- GetMesh()->SetEnableGravity(true); //开启重力效果
- GetMesh()->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly); //开启物理碰撞通道
- GetMesh()->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block); //开启角色与静态物体产生碰撞
- //关闭角色碰撞体碰撞通道,避免其对武器和角色模拟物理效果产生影响
- GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
- //设置角色溶解
- Dissolve();
- //设置死亡状态
- bDead = true;
-
- //触发死亡委托
- OnDeath.Broadcast(this);
- }
复制代码 在蓝图编辑
接着,我们在脚色积累增加一个Niagara组件,设置火的负面效果
- UPROPERTY(VisibleAnywhere) //火焰负面效果表现组件
- TObjectPtr<UDeBuffNiagaraComponent> BurnDeBuffComponent;
复制代码 在构造函数里初始化,并设置好对应的负面标签
- //初始化火焰负面效果组件
- BurnDeBuffComponent = CreateDefaultSubobject<UDeBuffNiagaraComponent>("BurnDeBuffComponent");
- BurnDeBuffComponent->SetupAttachment(GetRootComponent());
- BurnDeBuffComponent->DeBuffTag = FRPGGameplayTags::Get().DeBuff_Burn; //设置匹配的负面标签
复制代码 编译打开UE,可以看到,内里增加了对应的组件
我们可以在组件上设置使用的Niagara资产
还可以修改对应的DeBuff标签
实现完成后,我们需要举行测试,测试的主要内容是
- 在激活负面效果时,是否可以大概精确激活Niagara
- 在负面效果结束时,标签是否可以大概在脚色身上精确清除,Niagara是否可以大概主动结束
- 在激活负面效果时,脚色死亡是否可以大概主动制止激活等待烧毁。
假如都没有标题,根本上效果实现完毕。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |