1.创建标签
ARPG_GRIVITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_MustBeHeld);
ARPG_GRIVITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_MustBeHeld_Block);
ARPG_GRIVITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Player_Ability_Block);
ARPG_GRIVITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Player_Status_Blocking);
UE_DEFINE_GAMEPLAY_TAG(InputTag_MustBeHeld, "InputTag.MustBeHeld");
UE_DEFINE_GAMEPLAY_TAG(InputTag_MustBeHeld_Block, "InputTag.MustBeHeld.Block");
UE_DEFINE_GAMEPLAY_TAG(Player_Ability_Block, "Player.Ability.Block");
UE_DEFINE_GAMEPLAY_TAG(Player_Status_Blocking, "Player.Status.Blocking");
2。进入资产,创建block的蒙太奇
确保根运动未开启
需要创建循环动画
在ga内设置
然后创建一个gameplaycue
3.打开XMbWarriorFunctionLibrary
//计算player在格挡时的夹角是否有效
UFUNCTION(BlueprintPure, Category = "XMBWorrior|FunctionLibrary")
static bool IsValidBlock(AActor* InAttacker, AActor* InDefender);
bool UXMBWarriorFunctionLibrary::IsValidBlock(AActor* InAttacker, AActor* InDefender)
{
check(InAttacker && InDefender);
//计算夹角
const float DotResult = FVector::DotProduct(InAttacker->GetActorForwardVector(), InDefender->GetActorForwardVector());
const FString DebugString = FString::Printf(TEXT("dot result: %f %s"),DotResult, DotResult < -0.1f ? TEXT("valid") : TEXT("invalid"));
Debug::Print(DebugString,DotResult < -0.1f ? FColor::Green : FColor::Red);
return DotResult < -0.1f;
}
打开EnemyCombatComponent
void UEnemyCombatComponent::OnHitTargetActor(AActor* HitActor)
{
if (OverlappedActors.Contains(HitActor))
{
return;
}
OverlappedActors.AddUnique(HitActor);
//TODO: Implement block check
bool bIsValidBlock = false;
const bool bIsPlayerBlocking = UXMBWarriorFunctionLibrary::NativeDoesActorHaveTag(HitActor, XMBGameplayTags::Player_Status_Blocking);
const bool bIsMyAttackUnblockble = false;
if (bIsPlayerBlocking && !bIsMyAttackUnblockble)
{
//TODO:check if the block is valid
//通过被攻击的角度和角色当前的朝向计算夹角
bIsValidBlock = UXMBWarriorFunctionLibrary::IsValidBlock(GetOwningPawn(),HitActor);
}
FGameplayEventData EventData;
EventData.Instigator = GetOwningPawn();
EventData.Target = HitActor;
if (bIsValidBlock)
{
//TODO:Handle successful block
}
else
{
UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(
GetOwningPawn(),
XMBGameplayTags::Shared_Event_MeleeHit,
EventData
);
}
}
添加一个tag
ARPG_GRIVITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Player_Event_SuccessfulBlock);
UE_DEFINE_GAMEPLAY_TAG(Player_Event_SuccessfulBlock, "Player.Event.SuccessfulBlock");
然后打开EnemyCombatComponent,将成功被阻挡的tag发送出去
if (bIsValidBlock)
{
//阻挡成功将事件发送
UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(
HitActor,
XMBGameplayTags::Player_Event_SuccessfulBlock,
EventData
);
}
4。启动项目
当玩家成功阻挡后,转向enemy的方向
然后进行击退和阻挡成功的粒子
接下来制作完美格挡.我们需要在被攻击前的一定时间内进行一个时间的计算,来判断玩家是否在开启格挡技能的一定时间内受到了攻击。
首先,先获取当前玩家开启技能时游戏的时间
再新建一个gameplaycue
下一步需要制作完美格挡后,玩家再进行攻击时能直接进入轻攻击或者重攻击的最后一段。则需要再完美格挡后将一个标签发送出去,在进行攻击的时候进行检测即可
打开GA_Block
在完美格挡后进行调用
再打开lightattackmaster与heavyattackmaster
通过检查是否拥有tag来判断刚刚是否完美格挡