[55. HUD #5]

 

실제로 Item을 먹었을 때 캐릭터의 상태가 변경되도록 해보자.

 

// Main.h
public:
    void DecreamentHealth(float Amount);
    void Die();
    void IncreamentCoins(int32 Amount);
    
// Main.cpp
void AMain::DecreamentHealth(float Amount)
{
    if (Health - Amount <= 0.f)
    {
        Health -= Amount;
        Die();
    }
    else
    {
        Health -= Amount;
    }
}

void AMain::Die()
{
}

void AMain::IncreamentCoins(int32 Amount)
{
    Coins += Amount;
}

// Pickup.h
public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Coins")
    int32 CoinCount;

// Pickup.cpp
APickup::APickup()
{
    CoinCount = 1;
}

void APickup::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
    Super::OnOverlapBegin(OverlappedComponent, OtherActor, OtherComp, OtherBodyIndex, bFromSweep, SweepResult);

    UE_LOG(LogTemp, Warning, TEXT("Pickup::OnOverlapBegin()"));

    if (OtherActor)
    {
        AMain* Main = Cast<AMain>(OtherActor);
        if (Main)
        {
            Main->IncreamentCoins(CoinCount);
        }
    }
}

// Explosive.h
public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Damage")
    float Damage;

// Explosive.cpp
AExplosive::AExplosive()
{
    Damage = 15.f;
}

void AExplosive::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
    Super::OnOverlapBegin(OverlappedComponent, OtherActor, OtherComp, OtherBodyIndex, bFromSweep, SweepResult);

    UE_LOG(LogTemp, Warning, TEXT("Explosive::OnOverlapBegin()"));

    if (OtherActor)
    {
        // 캐스팅 실패시 nullptr 반환
        AMain* Main = Cast<AMain>(OtherActor);
        if (Main)
        {
            Main->DecreamentHealth(Damage);
        }
    }
}

 

에디터에서 별다른 작업 없이 코드만 작성해주면 잘 작동된다.

 

[56. HUD #6]

 

전력질주를 구현해보자.

Shift키의 Up/Down 여부에 따라 전력질주 상태 여부를 결정할 것이다.

 

// Main.h
UENUM(BlueprintType)
enum class EMovementStatus : uint8
{
    EMS_Normal UMETA(DisplayName="Normal"),
    EMS_Sprinting UMETA(DisplayName = "Sprinting"),
    EMS_MAX UMETA(DisplayName = "DefaultMAX") // 실제로 보여지지는 않고 열거형의 끝을 알려줌
};

public:
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Enums")
    EMovementStatus MovementStatus;

    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Running")
    float RunningSpeed;
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Running")
    float SprintingSpeed;

    bool bShiftKeyDown;

    /* Pressed down to enable sprinting */
    void ShiftKeyDown();

    /* Released to stop sprinting */
    void ShiftKeyUp();
    
    /* Set movement status and running speed */
    void SetMovementStatus(EMovementStatus Status);
    
// Main.cpp
AMain::AMain()
{
    RunningSpeed = 650.f;
    SprintingSpeed = 950.f;

    bShiftKeyDown = false;
}

void AMain::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
    PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
}

void AMain::SetMovementStatus(EMovementStatus Status)
{
    MovementStatus = Status;

    if (MovementStatus == EMovementStatus::EMS_Sprinting)
    {
        GetCharacterMovement()->MaxWalkSpeed = SprintingSpeed;
    }
    else
    {
        GetCharacterMovement()->MaxWalkSpeed = RunningSpeed;
    }
}

void AMain::ShiftKeyDown()
{
    bShiftKeyDown = true;
}

void AMain::ShiftKeyUp()
{
    bShiftKeyDown = false;
}

// MainAnimInstance.h
public:
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Movement)
    class AMain* Main;
    
// MainAnimInstance.cpp
void UMainAnimInstance::NativeInitializeAnimation()
{
    if (Pawn == nullptr)
    {
        // 이 애니메이션 인스턴스의 소유자를 가져옴
        Pawn = TryGetPawnOwner();
        if (Pawn)
        {
            Main = Cast<AMain>(Pawn);
        }
    }
}

void UMainAnimInstance::UpdateAnimationProperties()
{
    if (Pawn == nullptr)
    {
        Pawn = TryGetPawnOwner();
    }

    if (Pawn)
    {
        FVector Speed = Pawn->GetVelocity();
        FVector LateralSpeed = FVector(Speed.X, Speed.Y, 0.f);

        MovementSpeed = LateralSpeed.Size();

        bIsInAir = Pawn->GetMovementComponent()->IsFalling();

        if (Main == nullptr)
        {
            Main = Cast<AMain>(Pawn);
        }
    }
}

 

Shift키의 Up/Down 액션에 대해 바인딩을 해준다. 애니메이션의 상태 변환을 하려면 블루프린트에서 값에 접근해야 하므로 AMain을 캐스팅해서 가지고 있는다.

 

 

상태 머신의 구조는 위와 같이 변한다.

 

아직 전력질주 상태를 지정하지 못해서 애니메이션의 변화는 없다.

 

[정리]

 

  • 없음

'언리얼 엔진 > UE4 C++' 카테고리의 다른 글

[UE C++] Combat #1  (0) 2022.09.10
[UE C++] Gameplay Mechanics #7  (0) 2022.09.09
[UE C++] Gameplay Mechanics #5  (0) 2022.09.08
[UE C++] Gameplay Mechanics #4  (0) 2022.09.08
[UE C++] Gameplay Mechanics #3  (0) 2022.09.07

+ Recent posts