초보 코린이의 성장 일지

UE4 Behavior, AI Avoid EQS 본문

언리얼

UE4 Behavior, AI Avoid EQS

코오린이 2023. 8. 9. 15:00

Enemy에 감지 범위에 객체가 들어왔을때 텔레포트를 사용하여 도망칠 수 있도록 구현해 볼 것이다.

1. 각 Task와 EQS에 설정을 해준다.

1. Behavior 전체적인 노드 구조.


#include "BehaviorTree/CBTTaskNode_Equip.h"
#include "Global.h"
#include "Characters/CEnemy_AI.h"
#include "Characters/CAIController.h"
#include "Components/CStateComponent.h"
#include "Components/CStatusComponent.h"
#include "Weapons/CEquipment.h"

EBTNodeResult::Type UCBTTaskNode_Equip::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
	Super::ExecuteTask(OwnerComp, NodeMemory);

	// 현재 장착하고있는 무기와, 장착할 무기가 같다면 이미 성공이므로,
	if (Type == weapon->GetWeaponType()) 
		return EBTNodeResult::Succeeded;

	controller->StopMovement();
	switch (Type)
	{
		case EWeaponType::Sword: weapon->SetSwordMode(); break;
		case EWeaponType::Bow: weapon->SetBowMode(); break;
		case EWeaponType::Warp: weapon->SetWarpMode(); break;

	}

	return EBTNodeResult::InProgress; // 조건이 성공했다면, 대기

}

1. EquipTask로가서 Warp를 사용할수 있도록 등록해준다.


 

1. Weapon 4번에 Warp를 등록해준다.


#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "CAIBehaviorComponent.generated.h"

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class U2212_06_API UCAIBehaviorComponent : public UActorComponent
{
	GENERATED_BODY()
private:
	UPROPERTY(EditAnywhere, Category = "Key")
		FName AvoidLocationKey = "Avoid_Location";
        
public:
	FVector GetAvoidLocation();

};
#include "Components/CAIBehaviorComponent.h"
#include "Global.h"
#include "GameFramework/Character.h"
#include "BehaviorTree/BlackboardComponent.h"

FVector UCAIBehaviorComponent::GetAvoidLocation()
{
	return Blackboard->GetValueAsVector(AvoidLocationKey);
}

1. Blackboard에 Key를 사용하기 위해 함수로 넘겨준다.


수정 전 코드.

1. 원래 Warp를 사용하기 위해 조건이 정해져있었다. 

2. GetCursorLocationAndRotation이 false라는건 Player가 아닌 다른 객체라는 의미이다.

3. 결국 Player가 아니라면 return 되고 종료가 되버리는 조건을 변경시켜줘야 한다.

4. 그 코드는 아래에 작성해 놓을 것이다.

#pragma once

#include "CoreMinimal.h"
#include "Weapons/CDoAction.h"
#include "CDoAction_Warp.generated.h"

UCLASS(Blueprintable)
class U2212_06_API UCDoAction_Warp : public UCDoAction
{
	GENERATED_BODY()
    
public:
    virtual void BeginPlay
    (
        class ACAttachment* InAttachment,
        class UCEquipment* InEquipment,
        class ACharacter* InOwner,
        const TArray<FDoActionData>& InDoActionData,
        const TArray<FHitData>& InHitData
    );

public:
    void DoAction() override;
    
private:
    class UCAIBehaviorComponent* Behavior;

};
#include "Weapons/DoActions/CDoAction_Warp.h"
#include "Global.h"
#include "GameFramework/Character.h"
#include "GameFramework/PlayerController.h"
#include "Components/CStateComponent.h"
#include "Components/DecalComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/CAIBehaviorComponent.h"
#include "Weapons/CAttachment.h"

void UCDoAction_Warp::BeginPlay(ACAttachment* InAttachment, UCEquipment* InEquipment, ACharacter* InOwner, const TArray<FDoActionData>& InDoActionData, const TArray<FHitData>& InHitData)
{
	Super::BeginPlay(InAttachment, InEquipment, InOwner, InDoActionData, InHitData);

	Behavior = CHelpers::GetComponent<UCAIBehaviorComponent>(InOwner);
}

void UCDoAction_Warp::DoAction()
{
	CheckFalse(DoActionDatas.Num() > 0);
	CheckFalse(State->IsIdleMode());

	Super::DoAction();

	FRotator rotation;
	// GetCursorLocationAndRotation가 false라면 Player가 아닌 객체.
	if (GetCursorLocationAndRotation(MoveToLocation, rotation)) // MoveToLocation에 기록을 해놓는다.
	{
		// 높이를 보정해 놓지 않으면 땅에 묻히는 버그가 발생하므로, 일정 크기만큼 올려준다.
		float height = OwnerCharacter->GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
		MoveToLocation = FVector(MoveToLocation.X, MoveToLocation.Y, MoveToLocation.Z + height);

		// 이동할 회전 방향에서 Yaw값만 사용.
		float yaw = UKismetMathLibrary::FindLookAtRotation(OwnerCharacter->GetActorLocation(), MoveToLocation).Yaw;
		OwnerCharacter->SetActorRotation(FRotator(0, yaw, 0)); // 회전방향 yaw 돌려주기.

	}

	// 액션 실행
	DoActionDatas[0].DoAction(OwnerCharacter);

}

void UCDoAction_Warp::Begin_DoAction()
{
	Super::Begin_DoAction();

	if (!!PlayerController)
	{
		OwnerCharacter->SetActorLocation(MoveToLocation); // Warp 이동
		MoveToLocation = FVector::ZeroVector; // 다시 없애준다.

		return;
	}

	CheckNull(Behavior); // Player아닌 다른 객체라면,
	OwnerCharacter->SetActorLocation(Behavior->GetAvoidLocation()); // AI에 넣어놓은 위치값으로 이동시키기

}

1. Behavior이 있는지 없는지 유무에 따라 Player인지 Enemy인지 구분할 수 있게 된다.

2. GetCursorLocationAndRotation 조건에 들어가지 못해도 Warp를 사용하는 객체가 수행은 할 수 있어야 하므로, return을 지워준다.

3. Behavior에 있는 Key값을 가져와서 사용한다.


https://www.youtube.com/watch?v=fi8He5tlVko 

 

'언리얼' 카테고리의 다른 글

UE4 Behavior, AI Range, EQS  (0) 2023.08.08
UE4 Behavior, AI Abort, Range  (0) 2023.08.07
UE4 Behavior, AI Equip  (0) 2023.08.03
UE4 Behavior, AI Hitted  (0) 2023.07.31
UE4 Behavior, AI Action  (2) 2023.07.27
Comments