BossFight - Trace Check (플레이어)

김대겸·2025년 4월 30일

Trace 추적 (플레이어)

이번에는 공격 시 Trace Check를 실행 하고, 시각적으로 확인 할 수 있게 구현 해보겠다.

해당 기능은 WeaponBase를 상속 받는 모든 Class에서 사용 가능 하나, 각 EnemyWeapon의 경우, Mesh가 있는 무기일 수도 있고, 곰형태의 보스 처럼 몸에 부착되는 형식 인 경우도 있다.

이러한 점을 고려하여 상호작용가능한 객체를 구현 한 것 처럼 Interface를 통해 구현 해보자.

// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UWeaponInterface : public UInterface
{
	GENERATED_BODY()
};

class BOSSFIGHT_API IWeaponInterface
{
	GENERATED_BODY()

	// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
	virtual void AttackTrace() = 0;
};

다음으로 Trace Check에 사용할 콜리전 프리셋과, 오브젝트 채널을 생성하고, Test를 위해 BP_Bear에 BoxComponent를 추가, 콜리전 프리셋을 새로 생성한 Type으로 변경 하였다.

Trace에 필요한 정보를 담을 구조체를 생성하고, WeaponBase에 위의 Interface를 상속 시켜 자식 Class에서 구현 해보자.

USTRUCT(BlueprintType)
struct FBFWeaponCollisionData
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	FName StartSocket;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	FName EndSocket;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	bool bIsShow = false;
};

🎮 AWeaponBase.h

UCLASS()
class BOSSFIGHT_API AWeaponBase : public APropBase, public IWeaponInterface
{
	GENERATED_BODY()

public:
	AWeaponBase();

	FORCEINLINE EBFEquipType GetEquipType() const { return EquipType; }

	virtual void AttackTrace() override;
    //중략
};

🎮 APlayerWeapon.cpp

void APlayerWeapon::AttackTrace()
{
	FVector Start = Mesh->GetSocketLocation(CollisionData.StartSocket);
	FVector End = Mesh->GetSocketLocation(CollisionData.EndSocket);
	FVector BoxSize = WeaponCollision->GetScaledBoxExtent();

	TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes;
	ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_GameTraceChannel3));

	TArray<AActor*> ActorsToIgnore;
	ActorsToIgnore.Add(Cast<AActor>(GetOwner()));

	FHitResult HitResult;

	UKismetSystemLibrary::BoxTraceSingleForObjects(
		GetWorld(),
		Start, 
		End, 
		BoxSize, 
		GetActorRotation(),
		ObjectTypes, 
		false, 
		ActorsToIgnore,
		CollisionData.bIsShow ? EDrawDebugTrace::Persistent : EDrawDebugTrace::None,
		HitResult, 
		true);
}

다음으로 전투와 관련된 부분을 담당할 PawnCombetComponent를 작성 해보자, 기존처럼 PawnExtensionComponent를 상속받아 구현 하자.

🎮 UPawnCombetComponent.h

UCLASS()
class BOSSFIGHT_API UPawnCombetComponent : public UPawnExtensionComponent
{
	GENERATED_BODY()

public:
	UFUNCTION(BlueprintCallable)
	void ActivateWeaponTrace(EBFEquipType Type);
};

🎮 UPawnCombetComponent.h

void UPawnCombetComponent::ActivateWeaponTrace(EBFEquipType Type)
{
	UPawnEquipmentComponent* EquipmentComponent = Cast<IPawnEquipmentInterface>(GetOwner())->GetPawnEquipmentComponent();
	IWeaponInterface* WeaponInterface = Cast<IWeaponInterface>(EquipmentComponent->GetCurrentWeapon(Type));
	WeaponInterface->AttackTrace();
}

위와 같이 WeaponInterface를 통해 TraceCheck를 하도록 구현 하였다.

추가로 UPawnEquipmentComponent에 GetCurrentWeapon()함수를 추가하였다. 해당 함수는 CurrentWeaponMap에서 Type에 맞는 무기를 AWeaponBase* 형태로 반환 해주는 함수이다.

또한 기존의UPlayerEquipmentComponent의 GetPlayerCurrentWeapon()함수에서 GetCurrentWeapon()을 호출하고 Cast하도록 변경 하였다.

마지막으로 ActivateWeaponTrace()함수를 AnimNotifyState를 통해 호출 하도록 Blueprint를 구현 하였다.

작동 영상

다음에는 적 캐릭터에게 각 부위별로 Collision을 부착 시키는 기능을 구현 해보자.

0개의 댓글