Showing

[디자인 패턴] 다양한 인터랙션을 위한 Unreal 인터페이스 활용 본문

Design Pattern

[디자인 패턴] 다양한 인터랙션을 위한 Unreal 인터페이스 활용

RabbitCode 2023. 12. 12. 15:56

인터페이스는 '서로 관련되지 않은 클래스들'이 공통 함수 혹은 공통 함수 세트를 구현하도록 하는 데 사용한다.

 

다시 말해, 인터페이스 클래스는 다양한 클래스들이 비슷한 기능을 공유하도록 돕는 유용한 도구로,
서로 다른 클래스들이 동일한 함수들을 사용할 수 있게 해준다. 

ex ) 인터페이스 함수로 Call()이 있다면 Computer, IPhone, TV, Galaxy 클래스에 해당 인터페이스 함수를 구현할 수 있도록 할 수 있다. 심지어 냉장고에도 Call()을 붙일 수 있다.


이를 통해 관련이 없어 보이는 클래스들도 호환가능해지며, 특정 기능을 공유하게 된다

 

이러한 인터페이스는 언리얼에서 라인트레이스를 통해 인터랙션해야하는 다양한 오브젝트들에 저마다의 이벤트를 심고 싶을 때 적절하게 활용해볼 수 있다. 가령 방탈출 게임에서 가방, 박스, 물병, 핸드폰 등의 오브젝트들과 캐릭터는 상호작용하고 다른 이벤트를 볼 수 있어야 한다.



// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "Interactable.generated.h"

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

/**
 * 
 */
class THIRDPERSONTEMPLATE_API IInteractable
{
	GENERATED_BODY()
public:
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interactable")
	void Interact(AActor* Instigator);
};

 

인터페이스를 사용할 액터를 하나 추가로 만들어준다.

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Interactable.h"
#include "InterfaceUsingActor.generated.h"

UCLASS()
class THIRDPERSONTEMPLATE_API AInterfaceUsingActor : public AActor, public IInteractable
{
	GENERATED_BODY()
public:	
	// Sets default values for this actor's properties
	AInterfaceUsingActor();

	virtual void Interact_Implementation(AActor* OtherActor) override;
protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

};

 

Module.ThirdPersonTemplate.cpp.obj : error LNK2001: unresolved external symbol "public: virtual void __cdecl AInterfaceUsingActor::Interact_Implementation(class AActor *)" (?

 

 

그러나 빨간 줄이 사라지지 않을 텐데 반드시 함수 구현부를 작성해주어야 한다. 관련 이슈 질문은 아래와 같다.

https://stackoverflow.com/questions/15273578/c-error-lnk-unresolved-external-symbol-resulting-from-virtual-functions

 

C++: error LNK: unresolved external symbol, resulting from virtual functions

Overview of classes etc of my interface! Animal.H: class Animal { public: virtual void walk(); } Animals.CPP =EMPTY Cow.H: class Cow : public Animal { public: virtual void walk(); } He...

stackoverflow.com

void AInterfaceUsingActor::Interact_Implementation(AActor* OtherActor)
{
	// 상호작용 시 행동하는 코드 작성
	// 예 : 물체와 상호작용하는 로직
	GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, (TEXT("Interface , %s"), *OtherActor->GetName()));
}

 

언리얼 프로젝트에서 인터페이스 패턴을 활용하는 것은 아래 영상을 확인하면 특히 유용하다.

https://youtu.be/wNDrCcjtLdA?feature=shared

 

인터페이스 C++ 생성

 

다른 객체에 인터페이스 상속 후 오버라이드

 

어떤 행동을 할 지는 인터페이스 구현 클래스마다 다르게 설정해줄 수 있다.

 

 

라인트레이스를 통해 히트한 액터가 인터페이스 구현체인지 확인한다.

정적 클래스를 이용하여 커스텀한 인터페이스가 맞는지 확인한다.
히트한 타겟이 인터페이스 구현체가 맞다면 해당 인터페이스 함수를 실행시킬 수 있도록 한다.

인터랙트 인터페이스의 순수함수를 구현한 순수함수를 호출하기 때문에 그밖에 다른 casting이 필요 없다.

또한 아래와 같이 다른 코드 스타일로도 작성할 수 있다.

 

인터페이스 참고 자료

https://youtu.be/wNDrCcjtLdA?feature=shared