[UE] Behavior Tree: 무기 장착 Abort
Behavior Tree의 UCBTTaskNode 내에 AbortTask를 추가할 것이다. Task의 성공과 실패 외에도 Abort가 걸리는 상황을 추가하여 Behavior Tree 실행 중 Task가 빨리 또는 느리게 실행되어 문제가 되는 상황을 방지할 것이다. 일종의 예외처리도 가능하여 Abort는 대부분의 경우 Behavior Tree에 필수적으로 사용된다.
목차
Plugins |
||||
Weapon |
||||
Resource |
||||
Icon128.png weapon_thumbnail_icon.png |
||||
Source |
||||
Weapon | ||||
SWeaponCheckBoxes.h .cpp SWeaponDetailsView.h .cpp SWeaponDoActionData.h .cpp SWeaponEquipmentData.h .cpp SWeaponHitData.h .cpp SWeaponLeftArea.h .cpp Weapon.Build.cs WeaponAssetEditor.h .cpp WeaponAssetFactory.h .cpp WeaponCommand.h .cpp WeaponContextMenu.h .cpp WeaponModule.h .cpp WeaponStyle.h .cpp |
||||
Source | ||
BehaviorTree | ||
CBTService_Melee.h .cpp CBTTaskNode_Action.h .cpp CBTTaskNode_Equip.h .cpp CBTTaskNode_Hitted.h .cpp CBTTaskNode_Patrol.h .cpp CBTTaskNode_Speed.h .cpp CPatrol.h .cpp |
||
Characters | ||
CAIController.h .cpp CAnimInstance.h .cpp CEnemy.h .cpp CEnemy_AI.h.cpp CPlayer.h.cpp ICharacter.h .cpp |
||
Components | ||
CAIBehaviorComponent.h .cpp CFeetComponent.h .cpp CMontagesComponent.h .cpp CMovementComponent.h .cpp CStateComponent.h .cpp CStatusComponent.h .cpp CWeaponComponent.h .cpp CZoomComponent.h .cpp |
||
Notifies | ||
CAnimNotifyState_BeginAction.h .cpp CAnimNotifyState_BowString.h .cpp CAnimNotify_CameraShake.h .cpp CAnimNotify_End_Parkour.h .cpp CAnimNotifyState_EndAction.h .cpp CAnimNotify_EndState.h .cpp CAnimNotifyState.h .cpp CAnimNotifyState_CameraAnim.h .cpp CAnimNotifyState_Collision.h .cpp CAnimNotifyState_Combo.h .cpp CAnimNotifyState_Equip.h .cpp CAnimNotifyState_SubAction.h .cpp |
||
Parkour | ||
CParkourComponent.h .cpp | ||
Utilities | ||
CHelper.h CLog.h .cpp |
||
Weapons | ||
CArrow.h .cpp CAura.h .cpp CCamerModifier.h .cpp CGhostTrail.h .cpp CRotate_Object.h .cpp CThornObject.h .cpp CAnimInstance_Bow.h .cpp CAttachment_Bow.h .cpp CDoAction_Around.h .cpp CDoAction_Bow.h .cpp CDoAction_Combo.h .cpp CDoAction_Warp.h .cpp CSubAction_Around.h .cpp CSubAction_Bow.h .cpp CSubAction_Fist.h .cpp CSubAction_Hammer.h .cpp CSubAction_Sword.h .cpp CDoAction_Warp.h .cpp CAttachment.h .cpp CDoAction.h .cpp CEquipment.h .cpp CSubAction.h .cpp CWeaponAsset.h .cpp CWeaponData.h .cpp CWeaponStructures.h .cpp |
||
Global.h CGameMode.h .cpp U2212_06.Build.cs |
||
U2212_06.uproject | ||
무기 장착 Abort
CEquipment
CEquipment.h
더보기
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Weapons/CWeaponStructures.h"
#include "CEquipment.generated.h"
//직렬화하여 BP에서 사용가능하도록 DYNAMIC, 여러함수를 받을 수 있도록 MULTICAST 사용.
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FEquipmentEquip);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FEquipmentBeginEquip);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FEquipmentUnequip);
UCLASS()
class U2212_06_API UCEquipment : public UObject
{
GENERATED_BODY()
public:
//실시간으로 bEquipped로 가져온다. 주소로 가져온다.
FORCEINLINE bool GetBeginEquip() { return bBeginEquip; }
FORCEINLINE const bool* GetEquipped() { return &bEquipped; }
public:
void BeginPlay(class ACharacter* InOwner, const FEquipmentData& InData);
public:
UFUNCTION(BlueprintNativeEvent)//필요시 BP에서 재정의하기 위해 BlueprintNativeEvent사용.
void Equip();
void Equip_Implementation();
UFUNCTION(BlueprintNativeEvent)
void Begin_Equip();
void Begin_Equip_Implementation();
UFUNCTION(BlueprintNativeEvent)
void End_Equip();
void End_Equip_Implementation();
UFUNCTION(BlueprintNativeEvent)
void Unequip();
void Unequip_Implementation();
public:
FEquipmentEquip OnEquipmentEquip;//DECLARE_DYNAMIC_MULTICAST_DELEGATE 하였다.
FEquipmentBeginEquip OnEquipmentBeginEquip;//DECLARE_DYNAMIC_MULTICAST_DELEGATE 하였다.
FEquipmentUnequip OnEquipmentUnequip;//DECLARE_DYNAMIC_MULTICAST_DELEGATE 하였다.
private:
class ACharacter* OwnerCharacter;
FEquipmentData Data;
private:
class UCMovementComponent* Movement;
class UCStateComponent* State;
private:
bool bBeginEquip;//Equip이 시작되었는가 확인
bool bEquipped; //Equip이 완료되었는지 확인
};
인라인 함수
- FORCEINLINE bool GetBeginEquip() { return bBeginEquip; }
CEquipment.cpp
더보기
#include "Weapons/CEquipment.h"
#include "Global.h"
#include "GameFramework/Character.h"
#include "Components/CMovementComponent.h"
#include "Components/CStateComponent.h"
#include "CEquipment.h"
void UCEquipment::BeginPlay(ACharacter* InOwner, const FEquipmentData& InData)
{
OwnerCharacter = InOwner;
Data = InData;
Movement = CHelpers::GetComponent<UCMovementComponent>(InOwner);
State = CHelpers::GetComponent<UCStateComponent>(InOwner);
}
void UCEquipment::Equip_Implementation()
{
State->SetEquipMode();
if (OnEquipmentEquip.IsBound())//활 장착 확인?
OnEquipmentEquip.Broadcast();
if (Data.bCanMove == false)
Movement->Stop();
if (Data.bUseControlRotation)
Movement->EnableControlRotation();
if (!!Data.Montage)
{
OwnerCharacter->PlayAnimMontage(Data.Montage, Data.PlayRate);
}
else
{
Begin_Equip();
End_Equip();
}
}
void UCEquipment::Begin_Equip_Implementation()
{
bBeginEquip = true;
if (OnEquipmentBeginEquip.IsBound())
OnEquipmentBeginEquip.Broadcast();
}
void UCEquipment::End_Equip_Implementation()
{
bBeginEquip = false;
bEquipped = true;
Movement->Move();
State->SetIdleMode();
}
void UCEquipment::Unequip_Implementation()
{
bEquipped = false;
Movement->DisableControlRotation();
if (OnEquipmentUnequip.IsBound())
OnEquipmentUnequip.Broadcast();
}
변경사항 없음
CBTTaskNode_Equip
CBTTaskNode_Equip.h
더보기
#pragma once
#include "CoreMinimal.h"
#include "BehaviorTree/BTTaskNode.h"
#include "Components/CWeaponComponent.h"
#include "CBTTaskNode_Equip.generated.h"
UCLASS()
class U2212_06_API UCBTTaskNode_Equip : public UBTTaskNode
{
GENERATED_BODY()
private:
UPROPERTY(EditAnywhere, Category = "Type")
EWeaponType Type;
public:
UCBTTaskNode_Equip();
protected:
EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
void TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds) override;
EBTNodeResult::Type AbortTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
};
테스크 추가
- EBTNodeResult::Type AbortTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
CBTTaskNode_Equip.cpp
더보기
#include "BehaviorTree/CBTTaskNode_Equip.h"
#include "Global.h"
#include "Characters/CEnemy_AI.h"
#include "Characters/CAIController.h"
#include "Components/CStateComponent.h"
#include "Weapons/CEquipment.h"
UCBTTaskNode_Equip::UCBTTaskNode_Equip()
{
NodeName = "Equip";
bNotifyTick = true;
}
EBTNodeResult::Type UCBTTaskNode_Equip::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
Super::ExecuteTask(OwnerComp, NodeMemory);
ACAIController* controller = Cast<ACAIController>(OwnerComp.GetOwner());
ACEnemy_AI* ai = Cast<ACEnemy_AI>(controller->GetPawn());
UCWeaponComponent* weapon = CHelpers::GetComponent<UCWeaponComponent>(ai);
CheckNullResult(weapon, EBTNodeResult::Failed);//weapon이 없다면 EBTNodeResult::Failed 리턴
if (Type == weapon->GetWeaponType())//장착될 무기 == 현재 장착된 무기
return EBTNodeResult::Succeeded;//새로 장착시킬 필요 없으니 바로 Succeeded를 리턴
switch (Type)
{
case EWeaponType::Sword: weapon->SetSwordMode(); break;//Sword 장착
}
return EBTNodeResult::InProgress;//장착 동작이 나올 수 있도록 InProgress 리턴
}
void UCBTTaskNode_Equip::TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
Super::TickTask(OwnerComp, NodeMemory, DeltaSeconds);
ACAIController* controller = Cast<ACAIController>(OwnerComp.GetOwner());
ACEnemy_AI* ai = Cast<ACEnemy_AI>(controller->GetPawn());
UCWeaponComponent* weapon = CHelpers::GetComponent<UCWeaponComponent>(ai);//weapon을 가져온다.
const bool* bEquipped = weapon->GetEquipment()->GetEquipped();
UCStateComponent* state = CHelpers::GetComponent<UCStateComponent>(ai);
if(state->IsIdleMode() && *bEquipped)
{
FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
return;
}
}
EBTNodeResult::Type UCBTTaskNode_Equip::AbortTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
Super::AbortTask(OwnerComp, NodeMemory);
ACAIController* controller = Cast<ACAIController>(OwnerComp.GetOwner());
ACEnemy_AI* ai = Cast<ACEnemy_AI>(controller->GetPawn());
UCWeaponComponent* weapon = CHelpers::GetComponent<UCWeaponComponent>(ai);
if (weapon == nullptr)//무기가 없다면
{
FinishLatentAbort(OwnerComp);//중단으로 끝낸다.
return EBTNodeResult::Failed;//실패 리턴
}
bool bBeginEquip = weapon->GetEquipment()->GetBeginEquip();//GetBeginEquip()으로 CEquipment의 bBeginEquip를 넣어준다. bBeginEquip=true면 Equip이 시작되었다는 의미다.
if (bBeginEquip == false)
weapon->GetEquipment()->Begin_Equip();
weapon->GetEquipment()->End_Equip();
return EBTNodeResult::Aborted;//Aborted는 취소 마감, 위(Root)로 올라감. Succeeded는 성공종료.
}
테스크 정의
- EBTNodeResult::Type UCBTTaskNode_Equip::AbortTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
- if (weapon == nullptr) {
FinishLatentAbort(OwnerComp);
return EBTNodeResult::Failed;
} - bool bBeginEquip = weapon->GetEquipment()->GetBeginEquip();
- GetBeginEquip()으로 CEquipment의 bBeginEquip를 넣어준다. bBeginEquip=true면 Equip이 시작되었다는 의미다.
- if (bBeginEquip == false)
weapon->GetEquipment()->Begin_Equip(); - weapon->GetEquipment()->End_Equip();
- return EBTNodeResult::Aborted;
- Aborted는 취소 마감, 위(Root)로 올라감. Succeeded는 성공종료.
- if (weapon == nullptr) {
실행화면
활 조준 Zoom In 시 튕기는 오류해결
CPlayer
FPS처럼 Zoom이 일어나는 경우, 1인칭 시점 카메라를 추가해서 만들고 Zoom 시에 카메라 전환을 하여 1인칭 전용 카메라를 사용해준다.
CPlayer.h
더보기
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Components/CStateComponent.h"
#include "Characters/ICharacter.h"
#include "Parkour/CParkourComponent.h"
#include "GenericTeamAgentInterface.h"
#include "CPlayer.generated.h"
UCLASS()
class U2212_06_API ACPlayer
: public ACharacter, public IICharacter, public IGenericTeamAgentInterface //다중상속
{
GENERATED_BODY()
private:
UPROPERTY(EditDefaultsOnly, Category = "Team")
uint8 TeamID = 1;
private:
UPROPERTY(VisibleAnywhere)
class USpringArmComponent* SpringArm;
UPROPERTY(VisibleAnywhere)
class UCameraComponent* Camera;
private:
UPROPERTY(VisibleAnywhere)
class UCWeaponComponent* Weapon;
UPROPERTY(VisibleAnywhere)
class UCMontagesComponent* Montages;
UPROPERTY(VisibleAnywhere)
class UCMovementComponent* Movement;
UPROPERTY(VisibleAnywhere)
class UCStateComponent* State;
/** 파쿠르 */
private:
UPROPERTY(VisibleDefaultsOnly)
class USceneComponent* ArrowGroup;//파쿠르를 위한 ArrowGroup
UPROPERTY(VisibleDefaultsOnly)
class UArrowComponent* Arrows[(int32)EParkourArrowType::Max];
UPROPERTY(VisibleDefaultsOnly)
class UCParkourComponent* Parkour;
/** 파쿠르 */
UPROPERTY(VisibleDefaultsOnly)
class UCZoomComponent* Zoom;
public:
ACPlayer();
protected:
virtual void BeginPlay() override;
public:
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
FGenericTeamId GetGenericTeamId() const override { return FGenericTeamId(TeamID); }
private:
UFUNCTION()
void OnStateTypeChanged(EStateType InPrevType, EStateType InNewType);
private:
void OnAvoid();
private:
void BackStep();
public:
void End_BackStep() override;//ICharacter의 함수 오버라이드
public:
void OnRightButton();
void OffRightButton();
public:
void Landed(const FHitResult& Hit) override;//BP의 OnLanded C++버젼.
private:
void SetZooming(float InValue);
};
함수 수정 및 추가
- 변경 전:
- void Click_RightButton();
- 변경 후:
- void OnRightButton();
- void OffRightButton();
CPlayer.cpp
더보기
#include "Characters/CPlayer.h"
#include "Global.h"
#include "CAnimInstance.h"
#include "GameFramework/SpringArmComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Camera/CameraComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "Components/InputComponent.h"
#include "Components/CMontagesComponent.h"
#include "Components/CMovementComponent.h"
#include "Components/CWeaponComponent.h"
#include "Components/CZoomComponent.h"
#include "Components/ArrowComponent.h"
ACPlayer::ACPlayer()
{
CHelpers::CreateComponent<USpringArmComponent>(this, &SpringArm, "SpringArm", GetMesh());
CHelpers::CreateComponent<UCameraComponent>(this, &Camera, "Camera", SpringArm);
CHelpers::CreateActorComponent<UCWeaponComponent>(this, &Weapon, "Weapon");
CHelpers::CreateActorComponent<UCMontagesComponent>(this, &Montages, "Montages");
CHelpers::CreateActorComponent<UCMovementComponent>(this, &Movement, "Movement");
CHelpers::CreateActorComponent<UCStateComponent>(this, &State, "State");
CHelpers::CreateActorComponent<UCParkourComponent>(this, &Parkour, "Parkour");
CHelpers::CreateActorComponent<UCZoomComponent>(this, &Zoom, "Zoom");
GetMesh()->SetRelativeLocation(FVector(0, 0, -90));
GetMesh()->SetRelativeRotation(FRotator(0, -90, 0));
USkeletalMesh* mesh;
CHelpers::GetAsset<USkeletalMesh>(&mesh, "SkeletalMesh'/Game/Character/Mesh/SK_Mannequin.SK_Mannequin'");
GetMesh()->SetSkeletalMesh(mesh);
TSubclassOf<UCAnimInstance> animInstance;
CHelpers::GetClass<UCAnimInstance>(&animInstance, "AnimBlueprint'/Game/ABP_Character.ABP_Character_C'");
GetMesh()->SetAnimClass(animInstance);
SpringArm->SetRelativeLocation(FVector(0, 0, 140));
SpringArm->SetRelativeRotation(FRotator(0, 90, 0));
SpringArm->TargetArmLength = 200;
SpringArm->bDoCollisionTest = false;
SpringArm->bUsePawnControlRotation = true;
SpringArm->bEnableCameraLag = true;
GetCharacterMovement()->RotationRate = FRotator(0, 720, 0);
CHelpers::CreateComponent<USceneComponent>(this, &ArrowGroup, "ArrowGroup", GetCapsuleComponent());//ArrowGroup을 생성하고 GetCapsuleComponent 아래로 붙여준다.
//파쿠르에 활용한 Arrows들을 생성한다.
for (int32 i = 0; i < (int32)EParkourArrowType::Max; i++)
{
FString name = StaticEnum<EParkourArrowType>()->GetNameStringByIndex(i);
CHelpers::CreateComponent<UArrowComponent>(this, &Arrows[i], FName(name), ArrowGroup);
switch ((EParkourArrowType)i)
{
case EParkourArrowType::Center:
Arrows[i]->ArrowColor = FColor::Red;
break;
case EParkourArrowType::Ceil:
Arrows[i]->ArrowColor = FColor::Green;
Arrows[i]->SetRelativeLocation(FVector(0, 0, 100));
break;
case EParkourArrowType::Floor:
Arrows[i]->ArrowColor = FColor::Blue;
Arrows[i]->SetRelativeLocation(FVector(0, 0, -80));
break;
case EParkourArrowType::Left:
Arrows[i]->ArrowColor = FColor::Magenta;
Arrows[i]->SetRelativeLocation(FVector(0, -30, 0));
break;
case EParkourArrowType::Right:
Arrows[i]->ArrowColor = FColor::Magenta;
Arrows[i]->SetRelativeLocation(FVector(0, 30, 0));
break;
case EParkourArrowType::Land:
Arrows[i]->ArrowColor = FColor::Yellow;
Arrows[i]->SetRelativeLocation(FVector(200, 0, 100));
Arrows[i]->SetRelativeRotation(FRotator(-90, 0, 0));
break;
}
}
}
void ACPlayer::BeginPlay()
{
Super::BeginPlay();
Movement->OnRun(); //Movement의 기본을 Run으로 설정
Movement->DisableControlRotation();//Movement의 기본을 DisableControlRotation으로 설정
State->OnStateTypeChanged.AddDynamic(this, &ACPlayer::OnStateTypeChanged);
}
void ACPlayer::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis("MoveForward", Movement, &UCMovementComponent::OnMoveForward);
PlayerInputComponent->BindAxis("MoveRight", Movement, &UCMovementComponent::OnMoveRight);
PlayerInputComponent->BindAxis("VerticalLook", Movement, &UCMovementComponent::OnVerticalLook);
PlayerInputComponent->BindAxis("HorizontalLook", Movement, &UCMovementComponent::OnHorizontalLook);
PlayerInputComponent->BindAction("Sprint", EInputEvent::IE_Pressed, Movement, &UCMovementComponent::OnSprint);
PlayerInputComponent->BindAction("Sprint", EInputEvent::IE_Released, Movement, &UCMovementComponent::OnRun);
PlayerInputComponent->BindAction("Avoid", EInputEvent::IE_Pressed, this, &ACPlayer::OnAvoid);
//PlayerInputComponent->BindAxis("Zoom", Zoom, &UCZoomComponent::SetZoomValue);//Value로 연동되게하면 Bow 모드 시 문제가 될 수 있다.
PlayerInputComponent->BindAxis("Zoom", this, &ACPlayer::SetZooming);//Bow 모드가 아닐 때만 사용하려고 SetZooming으로 설정하여 만들었다.
PlayerInputComponent->BindAction("Fist", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetFistMode);
PlayerInputComponent->BindAction("Sword", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetSwordMode);
PlayerInputComponent->BindAction("Hammer", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetHammerMode);
PlayerInputComponent->BindAction("Warp", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetWarpMode);
PlayerInputComponent->BindAction("Around", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetAroundMode);
PlayerInputComponent->BindAction("Bow", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::SetBowMode);
PlayerInputComponent->BindAction("Action", EInputEvent::IE_Pressed, Weapon, &UCWeaponComponent::DoAction);
PlayerInputComponent->BindAction("SubAction", EInputEvent::IE_Pressed, this, &ACPlayer::OnRightButton);
PlayerInputComponent->BindAction("SubAction", EInputEvent::IE_Released, this, &ACPlayer::OffRightButton);
}
void ACPlayer::OnStateTypeChanged(EStateType InPrevType, EStateType InNewType)
{
switch (InNewType)
{
case EStateType::BackStep: BackStep(); break;
}
}
void ACPlayer::OnAvoid()
{
CheckFalse(State->IsIdleMode());
CheckFalse(Movement->CanMove());
CheckTrue(InputComponent->GetAxisValue("MoveForward") >= 0.0f);//뒷방향을 입력했다면
State->SetBackStepMode();//State을 BackStepMode로 변경한다.
}
void ACPlayer::BackStep()
{
Movement->EnableControlRotation();//정면을 바라본 상태로 뒤로 뛰어야하기 때문에 EnableControlRotation으로 만들어준다.
Montages->PlayBackStepMode();//PlayBackStepMode()를 통해 몽타주 재생.
}
void ACPlayer::End_BackStep()
{
Movement->DisableControlRotation();//Backstep이 끝나면 원래대로 돌려준다.
State->SetIdleMode();//Idle상태로 돌려줌.
}
void ACPlayer::OnRightButton()
{
if (Weapon->IsUnarmedMode())
{
Parkour->DoParkour();
return;
}
if (Weapon->IsBowMode())
{
//BowMode(활 장착)일 때 우클릭을 누르고 있을때 Zoom기능을 꺼준다.
Zoom->SetComponentTickEnabled(false);
}
Weapon->SubAction_Pressed();
}
void ACPlayer::OffRightButton()
{
if (Weapon->IsBowMode())
{
//BowMode(활 장착)일 때 우클릭을 떼면 Zoom기능을 꺼준다.
Zoom->SetComponentTickEnabled(true);
}
Weapon->SubAction_Released();
}
void ACPlayer::Landed(const FHitResult& Hit)
{
Parkour->DoParkour(true);
}
void ACPlayer::SetZooming(float InValue)
{
CheckTrue(Weapon->IsBowMode());//BowMode이면 바로 리턴
Zoom->SetZoomValue(InValue);//BowMode가 아닌 경우 Zoom In&Out 가능.
}
함수 수정 및 추가
- void ACPlayer::OnRightButton()
- if (Weapon->IsBowMode()) { Zoom->SetComponentTickEnabled(false); }
- Weapon->SubAction_Pressed();
- void ACPlayer::OffRightButton()
- if (Weapon->IsBowMode()) { Zoom->SetComponentTickEnabled(true); }
- Weapon->SubAction_Released();
'⭐ Unreal Engine > UE RPG AI' 카테고리의 다른 글
[UE] Behavior Tree: 활 조준 및 발사하기 (0) | 2023.08.08 |
---|---|
[UE] Behavior Tree: 활 Enemy 생성, Player 바라보기 (0) | 2023.08.07 |
[UE] Behavior Tree: 피격(Hitted) (0) | 2023.07.31 |
[UE] Behavior Tree: 무기 장착 및 공격 (0) | 2023.07.27 |
[UE] Behavior Tree: 무기 장착(Equip) (0) | 2023.07.26 |
댓글
이 글 공유하기
다른 글
-
[UE] Behavior Tree: 활 조준 및 발사하기
[UE] Behavior Tree: 활 조준 및 발사하기
2023.08.08 -
[UE] Behavior Tree: 활 Enemy 생성, Player 바라보기
[UE] Behavior Tree: 활 Enemy 생성, Player 바라보기
2023.08.07 -
[UE] Behavior Tree: 피격(Hitted)
[UE] Behavior Tree: 피격(Hitted)
2023.07.31 -
[UE] Behavior Tree: 무기 장착 및 공격
[UE] Behavior Tree: 무기 장착 및 공격
2023.07.27