개인프로젝트

[Unreal_C++_DarkSoul]#9_기능 구현, Status Effect 기능

Hardii2 2022. 12. 18. 14:45

 

[Unreal_C++_DarkSoul]#9_Status Effect

 

Weapon의 Skill 공격 시 고유의 Attribute와 매치되는 상태 이상 효과를 구현합니다

Unreal 포트폴리오 작업 과정을 기록합니다.


 

Overview

 

  1. 개요
  2. 설계
  3. 상세 내용
  4. 게임 플레이 화면

 

개요

1. 상태 이상 효과

 

  • 각 Weapon은 고유의 Attribute(속성)을 갖도록 합니다.
  • 그리고, 각 Attribute는 Weapon의 스킬 공격 시 피격 대상에게 물리 대미지뿐만 아니라, 특별한 상태 이상 효과를 유발합니다.
  • 예를 들면, 불 속성의 무기는 특정 스킬 공격 시 피격 대상에게 물리 데미지 뿐만 아니라, DoT 데미지를 전달하는 "화상" 효과를 유발합니다.
  • 총 5가지 상태 이상 효과를 구현합니다.
  • "Burn(화상)", "Frozen(스턴)", "Threat(공포)", "Electric Shock(스턴)", 그리고 "Debuff(방어력 감소)"

 

 

설계

1. 설계

 

  1. Damage Type 클래스 선언 및 정의
  2.  Status Effect 클래스 선언 및 정의
  3. Heatlh Component와 Damage Type 클래스가 공통으로 활용할 인터페이스 클래스 구현

 

Details

 

  1. Damage Type 클래스는 Weapon이 피격 대상에게 전달하는 대미지에 대한 정보를 담고 있습니다.
  2. 각 Damage Type 클래스는 고유의 상태 이상 효과(Status Effect)를 유발합니다.
  3. 그리고, 각 "상태 이상 효과"는 활성화 시 주어진 고정 시간 동안 피격 대상에게 특별한 대미지를 전달합니다.
  4. 피격 대상의 Health Component는 전달 받은 Damage Type 클래스를 통해 상태 이상 효과 유발 여부를 확인.

 

상세 코드

1. Custom_Enums.h

//...

UENUM(BlueprintType)
enum class EAttributeType : uint8
{
	E_Fire	= 0			UMETA(DisplayName = "Fire"),
	E_Ice				UMETA(DisplayName = "Ice"),
	E_Electric			UMETA(DisplayName = "Electric"),
	E_Dark				UMETA(DisplayName = "Dark"),
	E_Steel 			UMETA(DisplayName = "Steel"),
	E_Max				UMETA(DisplayName = "Max"),
};

//...

 

Details

 

  • 앞으로 구현할 상태 이상 효과 클래스마다 갖는 고유의 속성 값을 정의하기 위해 속성 열거형을 정의합니다.
  • Damage Type 클래스와 Status Effect 클래스를 연결할 매개체로 활용됩니다.

 

2. DamageTypeHealthInterface.cpp

/*	********************************************************************************************************
		
[Remark]: Add UFUNCTION() Reflection On Unreal Editor Makes Error

목적:	
	"C_HealthComponent" 객체의 포인터를 "참조형"으로 인자를 넘겨 받아 "Out Parameter"로 활용하고자 합니다.
설명:
	1. UFUNCTION()을 작성하면, Out Parameter로 받을 시 Log(Missing '*' in Expected a pointer type)가 발생합니다.
	2. UFUNCTION()을 지우니까, 에러가 발생하지 않는 특이한 점을 발견합니다.

*********************************************************************************************************/
public:
    virtual void TriggerStatusEffect(class UC_HealthComponent* OutComp) = 0;

 

Details

 

  • Health Component와 Damage Type이 공통으로 상속하는 인터페이스 클래스를 생성합니다.
  • "TriggerStatusEffect()" 순수 가상 함수를 선언합니다.
  • 이후, Damage Type 클래스에서 "TriggerStatusEffect()" 가상 함수를 오버 라이딩합니다.

 

3. DT_Burn.cpp

void UDT_Burn::TriggerStatusEffect(UC_HealthComponent* OutComp)
{
	OutComp->TriggerStatusEffect(EAttributeType::E_Fire);
}

 

4. DT_Frozen.cpp

void UDT_Frozen::TriggerStatusEffect(UC_HealthComponent* OutComp)
{
	OutComp->TriggerStatusEffect(EAttributeType::E_Ice);
}

 

 

Details

 

  • Weapon이 전달한 Damage Type 클래스는 피격 대상의 Health Component를 인자로 받아 하여금 알맞은 상태 이상 효과를 유발합니다.
  • 눈여겨볼 점은 각 대미지 타입 클래스는 각각 다른 EAttributeType을 HealthComponent의 "TriggetStatusEffect()" 함수에 전달하고 있습니다! 
  • 따라서, Damage 관련 이벤트가 발생하면, 피격 대상의 Health Component에게 전달된 각기 다른 Damage Type 클래스로 하여금 각기 다른 상태 이상 효과를 유발하도록 합니다.

 

5. SE_Burn::StartActivation()

void ASE_Burn::StartActivation()
{

    Super::StartActivation();

    AActor* AttachActor = GetOwner();
    CheckNull(AttachActor);

    // Timer
    FTimerDelegate TimerDelegate = FTimerDelegate::CreateUObject(this, &ASE_Burn::SendDamage, AttachActor );
    GetWorldTimerManager().SetTimer(TimerHandler,  TimerDelegate, DamageRate, true);

}

 

6. SE_Frozen::StartActivation()

void ASE_Frozen::StartActivation()
{

    Super::StartActivation();

    AActor* AttachActor = GetOwner();
    CheckNull(AttachActor);

    ACharacter* AttachCharacter = Cast<ACharacter>(AttachActor);
    CheckNull(AttachCharacter);

    // 1. Change Material
    ChangeMaterialFrozen(&AttachCharacter);

    // 2. Stop Movement
    StopCharacterMovement(&AttachActor);

    // 3. Timer For End Activation
    GetWorld()->GetTimerManager().SetTimer(TimerHandler, this, &ASE_Frozen::EndActivation, DamageRate, false);

}

 

Details

 

  1. 상태 이상 효과는 크게 두 가지 카테고리를 가집니다 - DoT, 스턴, 그리고 Debuff
  2. 각 상태 이상 효과 클래스는 기본적으로 3가지 패턴을 통해 피격 대상에게 상태 이상 효과를 유발하고, 세부적으로 특별한 Particle을 화면에 렌더링 합니다.

 

7. HealthComponent::TriggerStatusEffect()

void UC_HealthComponent::TriggerStatusEffect(EAttributeType InAttributeType)
{
	CheckFalse(StatusEffectClasses.IsValidIndex((int32)InAttributeType));

	AActor* OwnerActor = GetOwner();
	CheckNull(OwnerActor);

	AGameObject* OwnerObject = Cast<AGameObject>(OwnerActor);
	CheckNull(OwnerObject);

	StatusEffect = GetWorld()->SpawnActor<AStatusEffect>(StatusEffectClasses[((int32)InAttributeType)]);
	StatusEffect->SetOwner(OwnerObject);	
	StatusEffect->AttachComponentToOwnerComponent(OwnerObject->GetMesh());

	StatusEffect->StartActivation();

}

 

Details

 

  • Health Component는 인자로 전달받은 속성 값을 통해 미리 갖고 있는 상태 이상 효과 클래스들의 목록을 탐색하여 알맞은 상태 이상 효과를 활성화시킵니다.

 

게임 플레이 화면