• 아이템을 통과하면 빈속의 아이템을 쥐어주는 기능을 구현
  • 아이템 상자에 클래스를 정보를 저정할 속성을 추가
  • 아이템 영역에 들어왔을 떄 아이템을 생성하도록 구현
  • 특정클래스와 상속받은 클래스들로 목록을 한정하도록 TSubclassof라는 키워드를 제공
  • 사용하면 목록에서 아이템 상자와 이를 선언한 클래스 목록만 볼수 있다. UCLASS일 경우 모든 오브젝트의 선언이 보이게됨
//.h
class KGAME_API AABItemBox : public AActor
{
...
    UPROPERTY(EditInstanceOnly, Category = Box)
        TSubclassOf<class AABWeapon > WeaponItemClass;
}
//.cpp
AABItemBox::AABItemBox()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = false;

    Trigger = CreateDefaultSubobject<UBoxComponent>(TEXT("TRIGGER"));
    Box = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BOX"));

    RootComponent = Trigger;
    Box->SetupAttachment(RootComponent);

    Trigger->SetBoxExtent(FVector(40.0f, 42.0f, 30.0f));
    static ConstructorHelpers::FObjectFinder<UStaticMesh> SM_BOX(TEXT(
        "/Game/InfinityBladeGrassLands/Environments/Breakables/StaticMesh/Box/SM_Env_Breakables_Box1.SM_Env_Breakables_Box1"));

    if (SM_BOX.Succeeded())
    {
        Box->SetStaticMesh(SM_BOX.Object);
    }
    Box->SetRelativeLocation(FVector(0.0f, -3.5f, -30.0f));


    Trigger->SetCollisionProfileName(TEXT("ItemBox"));
    Box->SetCollisionProfileName(TEXT("NoCollision"));


    WeaponItemClass = AABWeapon::StaticClass();
}
AABItemBox::AABItemBox()
{
...
    WeaponItemClass = AABWeapon::StaticClass();
}

 


 

/.h
class KGAME_API AABCharacter : public ACharacter
{
...
public:
    UPROPERTY(VisibleAnyWhere, Category = Weapon)
        class AABWeapon* CurrentWeapon;

    bool CanSetWeapon();
    void SetWeapon(class AABWeapon* NewWeapon);

 //.cpp

  bool AABCharacter::CanSetWeapon()
{
    return (nullptr == CurrentWeapon);
}

void AABCharacter::SetWeapon(class AABWeapon* NewWeapon)
{
    FName WeaponSocket(TEXT("hand_rSocket"));
    if (nullptr != NewWeapon)
    {
        NewWeapon->AttachToComponent(GetMesh(),
            FAttachmentTransformRules::SnapToTargetNotIncludingScale, WeaponSocket);
        NewWeapon->SetOwner(this);
        CurrentWeapon = NewWeapon;
    }
}

 

Overlap 이벤트가 발생할떄 아이템 상자에 설정된 클래스 정보로 부터 무기를 생성하고 이를 캐릭터에게 장착시키는 기능을 구현

void AABItemBox::OnCharacterOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, 
    bool bFromSweep, const FHitResult& SweepResult)
{
    auto ABCharacter = Cast<AABCharacter>(OtherActor);

    if (nullptr != ABCharacter && nullptr != WeaponItemClass)
    {
        if (ABCharacter->CanSetWeapon())
        {
            auto NewWeapon = GetWorld()->SpawnActor<AABWeapon>(WeaponItemClass, FVector::ZeroVector,FRotator::ZeroRotator);
            ABCharacter->SetWeapon(NewWeapon);

        }
        else
        {
//장비 할수 없다
        }
    }
}

 

이펙트 재생 및 아이템상자 제거
멤버 함수를 하나 추가하고 파티클 컴포넌트 시스템에서 제공하는 OnSystemFinished 델리게이트에 이를 연결해 이펙트 재생이 종료되면 아이템 상자가 제거되도록 로직을 구성한다.
이때 OnSystemFinished델리게이트는 다이나믹 델리게이트 형식이다.
다이나믹 델리게이트에는 UFUNCTION 함수를 사용해야 하므로 아쉽게도 C++ 람다식으로 표현한 함수는 바인딩 할 수 없다

 

//.h
class KGAME_API AABItemBox : public AActor
{
    UPROPERTY(VisibleAnywhere, Category = Box)
        UParticleSystemComponent* Effect;

    UFUNCTION()
        void OnEffectFinished(class UParticleSystemComponent* PSystem);
};

//.cpp
AABItemBox::AABItemBox()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = false;

    Trigger = CreateDefaultSubobject<UBoxComponent>(TEXT("TRIGGER"));
    Box = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BOX"));
    Effect = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("EFFECT"));

    RootComponent = Trigger;
    Box->SetupAttachment(RootComponent);
    Effect->SetupAttachment(RootComponent);

    Trigger->SetBoxExtent(FVector(40.0f, 42.0f, 30.0f));
    static ConstructorHelpers::FObjectFinder<UStaticMesh> SM_BOX(TEXT(
        "/Game/InfinityBladeGrassLands/Environments/Breakables/StaticMesh/Box/SM_Env_Breakables_Box1.SM_Env_Breakables_Box1"));

    if (SM_BOX.Succeeded())
    {
        Box->SetStaticMesh(SM_BOX.Object);
    }
    Box->SetRelativeLocation(FVector(0.0f, -3.5f, -30.0f));


    static ConstructorHelpers::FObjectFinder<UParticleSystem> P_CHESTOPEN(TEXT(
        "/Game/InfinityBladeGrassLands/Effects/FX_Treasure/Chest/P_TreasureChest_Open_Mesh.P_TreasureChest_Open_Mesh"));
    if (P_CHESTOPEN.Succeeded())
    {
        Effect->SetTemplate(P_CHESTOPEN.Object);
        Effect->bAutoActivate = false;
    }

    Trigger->SetCollisionProfileName(TEXT("ItemBox"));
    Box->SetCollisionProfileName(TEXT("NoCollision"));

    WeaponItemClass = AABWeapon::StaticClass();
}


void AABItemBox::OnCharacterOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, 
    bool bFromSweep, const FHitResult& SweepResult)
{
    auto ABCharacter = Cast<AABCharacter>(OtherActor);

    if (nullptr != ABCharacter && nullptr != WeaponItemClass)
    {
        if (ABCharacter->CanSetWeapon())
        {
            auto NewWeapon = GetWorld()->SpawnActor<AABWeapon>(WeaponItemClass, FVector::ZeroVector,FRotator::ZeroRotator);
            ABCharacter->SetWeapon(NewWeapon);
            Effect->Activate(true);
            SetActorEnableCollision(false);
            Effect->OnSystemFinished.AddDynamic(this, &AABItemBox::OnEffectFinished);
        }
        else
        {

        }
    }
}


void AABItemBox::OnEffectFinished(class UParticleSystemComponent* PSystem)
{
    Destroy();

}

+ Recent posts