몬스터의 공격을 구현하였습니다.
캐릭터의 거리를 받아와 일정 거리 안에 들어왔을 시 공격을 시도하는 방식으로 구현했습니다.
EBTNodeResult::Type UBTTask_Attack::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
EBTNodeResult::Type Result = Super::ExecuteTask(OwnerComp, NodeMemory);
APawn* ControllingPawn = Cast<APawn>(OwnerComp.GetAIOwner()->GetPawn());
if (nullptr == ControllingPawn)
{
return EBTNodeResult::Failed;
}
ISLBearAIInterface* AIPawn = Cast<ISLBearAIInterface>(ControllingPawn);
if (nullptr == AIPawn)
{
return EBTNodeResult::Failed;
}
FAICharacterAttackFinished OnAttackFinished;
OnAttackFinished.BindLambda(
[&]()
{
FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
}
);
AIPawn->SetAIAttackDelegate(OnAttackFinished);
AIPawn->AttackByAI();
return EBTNodeResult::InProgress;
}
SetAIAttackDelegate를 사용하여 공격이 끝났을 때 OnAttackFinished를 Bind, AttackByAI를 실행시킵니다.
void ASLEnemyBearCharacter::AttackByAI()
{
UE_LOG(LogTemp, Log, TEXT("Attack Start"));
// Movement Setting
GetCharacterMovement()->SetMovementMode(EMovementMode::MOVE_None);
// Animation Setting
const float AttackSpeedRate = 1.0f;
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
AnimInstance->Montage_Play(ActionMontage, AttackSpeedRate);
//Set MontageEnd Delegate
FOnMontageEnded EndDelegate;
EndDelegate.BindUObject(this, &ASLEnemyBearCharacter::ComboActionEnd);
AnimInstance->Montage_SetEndDelegate(EndDelegate, ActionMontage);
UE_LOG(LogTemp, Log, TEXT("Attack Complete"));
}
void ASLEnemyBearCharacter::NotifyActionEnd()
{
OnAttackFinished.ExecuteIfBound();
}
void ASLEnemyBearCharacter::ComboActionEnd(UAnimMontage* TargetMontage, bool IsProperlyEnded)
{
UE_LOG(LogTemp, Log, TEXT("Attack End"));
GetCharacterMovement()->SetMovementMode(EMovementMode::MOVE_Walking);
NotifyActionEnd();
}
ASLEnemyBearCharacter부분에서 AttackByAI를 실행시키며 몽타주를 시작합니다.
몽타주의 끝나는 부분에 ComboActionEnd를 Bind하고 ComboActionEnd가 작동할 시 다시 움직일 수 있게 만들어줍니다.
마지막으로 NotifyActionEnd를 발동시키면서 BTTask_Attack을 끝내게 됩니다.