1. 개요
액터 위에 마우스 커서를 올려놓을 경우 하이라이트를 표시하는 기능을 구현해보자.

하이라이트 기능은 플레이어의 혼동을 줄여줄 수 있다.
적이 겹쳐있을 때 현재 어떤 적을 가리키고 있는지 명시적으로 표시해줄 수 있다.
2. 구현 아이디어
1. 마우스 커서로 액터를 감지한다.
PlayerController에서 GetHitResultUnderCursor함수를 제공한다. (공식 문서)
해당 함수는 커서 아래 어떤 액터가 감지되었는지 반환해준다.
액터가 감지되기 위해서는 메쉬를 가지고 있어야 하며
메쉬의 콜리전 채널 중 'Visibility'가 Block으로 설정되어 있어야 한다.
2. 인터페이스로 액터를 구별한다.

- 플레이어 컨트롤러에서 매 프레임마다 커서를 감지한다.
- 감지된 대상이 적(Enmey)인 경우에만 하이라이트 기능을 활성화 해야한다.
- 대상이 IEnemyInterface를 구현하였는지를 확인하여 구별한다.
3. 마우스 커서에 따라 하이라이트 활성화/비활성화한다.
마우스 커서에 따라 하이라이트 또는 언하이라이트를 실행해야 한다.
다음과 같은 경우들이 있다.
- 마우스 커서가 올라가면 하이라이트를 해야한다.
- 마우스 커서가 내려가면 언하이라이트를 해야한다.
- A 하이라이트 중 다른 대상(B)를 가리키게 되면 B 하이라이트하고 A는 언하이라이트 해야한다.
그래서 하이라이트를 구현하기 위해서는 이전에 어떤 대상을 가리켰는지 변수로 저장하고 있어야 한다.
4. 머터리얼 적용하기
머터리얼을 적용하려면 포스트 프로세스 볼륨, Custom Depth Stencil, 머터리얼이 필요하다.
포스트 프로세스 볼륨은 머터리얼을 전역 범위에 있는 모든 액터들에게 설정할 수 있다.
메쉬는 Custom Depth Stencil을 속성으로 가지고 있으며 값을 설정할 수 있다.
머터리얼에서는 메쉬에서 Custom Depth Stencil을 가져와 사용할 수 있다.
즉, 포스트 프로세스 볼륨에서 전역으로 머터리얼을 적용하되
머터리얼 내부에서 Custom Depth Stencil 값이 일치한 메쉬들을 대상으로 붉은 빛 효과를 적용할 수 있다.
2. 구현 프로세스
- IEnemyInterface 인터페이스를 생성한다.
- IEnemyInterface 인터페이스를 구현한 AAuraEnemy 클래스를 생성한다.
- PlayerController에서 매 프레임마다 커서 아래 액터를 감지하는 기능을 구현한다.
- CustomDepth 환경을 설정한다.
- PostProcess 생성한다.
2.1 IEnemyInterface 인터페이스를 생성한다.
1. 언리얼 인터페이스 생성하기

- 파일 경로는 "public/Interaction/EnemyInterface"로 생성한다.
2. 인터페이스 정의하기

UINTERFACE(MinimalAPI)
class UEnemyInterface : public UInterface
{
GENERATED_BODY()
};
class AURA_API IEnemyInterface
{
GENERATED_BODY()
public:
virtual void HighlightActor() abstract;
virtual void UnHighlightActor() abstract;
};
- HighlightActor(), UnHighlightActor()를 순수 가상함수로 선언한다.
2. Enemy 클래스 구현하기
/* AAuraEnemy.h */
UCLASS()
class AURA_API AAuraEnemy : public AAuraCharacterBase, public IEnemyInterface
{
GENERATED_BODY()
public:
AAuraEnemy();
/* IEnemyInterface 상속 */
virtual void HighlightActor() override;
virtual void UnHighlightActor() override;
/* end EnemyInterfcae */
}
- Enemy 클래스에서 IEnemyInterface의 순수 가상함수를 오버라이드한다.
/* AAuraEnemy.cpp */
AAuraEnemy::AAuraEnemy()
{
GetMesh()->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
GetMesh()->SetCustomDepthStencilValue(250.f);
}
void AAuraEnemy::HighlightActor()
{
GetMesh()->SetRenderCustomDepth(true);
_weapon->SetRenderCustomDepth(true);
}
void AAuraEnemy::UnHighlightActor()
{
GetMesh()->SetRenderCustomDepth(false);
_weapon->SetRenderCustomDepth(false);
}
- 메시의 콜리전 채널 중 "Visibility"를 Block으로 설정한다. (GetHitResultUnderCursor 함수에서 감지될 수 있다.)
- CustomDepthStencilValue를 250.f로 설정한다. (머터리얼에서 참조할 값이다.)
- 하이라이트시 메쉬의 RenderCustomDepth를 활성화한다.
- 언하이라이트시 메쉬의 RenderCustomDepth를 비활성화한다.
3. PlayerController에서 마우스로 대상 감지하기
/* PlayerController.h */
UCLASS()
class AURA_API AAuraPlayerController : public APlayerController
{
public:
virtual void PlayerTick(float DeltaTime) override;
private:
void CursorTrace();
TScriptInterface<IEnemyInterface> _prevTarget;
TScriptInterface<IEnemyInterface> _currentTarget;
}
- PlayerTick(float DeltaTime) : 매 프레임마다 호출되는 함수이다.
- CusorTrace() : 마우스로 대상을 감지하는 기능을 수행한다.
/* PlayerController.cpp */
void AAuraPlayerController::PlayerTick(float DeltaTime)
{
Super::PlayerTick(DeltaTime);
CursorTrace();
}
void AAuraPlayerController::CursorTrace()
{
FHitResult HitResult;
GetHitResultUnderCursor(ECC_Visibility, false, HitResult);
if (HitResult.bBlockingHit == false) return;
_prevTarget = _currentTarget;
_currentTarget = HitResult.GetActor();
if (_prevTarget == nullptr)
{
if (_currentTarget == nullptr)
{
// Case A
// Do Nothing
}
else
{
// Case B
_currentTarget->HighlightActor();
}
}
else
{
if (_currentTarget == nullptr)
{
// Case C
_prevTarget->UnHighlightActor();
}
else
{
if (_currentTarget != _prevTarget)
{
// Case D
_prevTarget->UnHighlightActor();
_currentTarget->HighlightActor();
}
else
{
// Case E
// Do Nothing
}
}
}
}
- 매 프레임마다 CusorTrace() 함수를 호출한다.
- CusorTrace() 함수에서는 다양한 상황에서 대상을 하이라이트 또는 언하이라이트 한다.
- 이전 대상 (NULL) & 현재 대상 (NULL)
- 아무것도 하지 않는다.
- 이전 대상 (NULL) & 현재 대상 (Vaild)
- 감지가 되었다. 현재 대상을 하이라이트 한다.
- 이전 대상 (Valid) & 현재 대상 (Valid)
- 이전 대상과 현재 대상을 비교한다.
- 동일하다면 아무것도 하지 않는다.
- 동일하지 않다면 이전 대상을 언하이라이트, 현재 대상을 하이라이트한다.
- 이전 대상과 현재 대상을 비교한다.
- 이전 대상 (Valid) & 현재 대상 (NULL)
- 감지가 풀렸다. 이전 대상을 언하이라이트 한다.
- 이전 대상 (NULL) & 현재 대상 (NULL)
4. Custom Depth 환경설정을 한다.

- Custom Depth-Stencil Pass를 'Enabled with Stencil'로 활성화한다.
5. Post Process Volume을 생성한다.

- Post Process Volume을 레벨에 생성한다.

- Post Process Volume을 클릭하여 디테일 패널에서 Infinite Extent를 활성화한다.
- 모든 영역에 볼륨 효과가 적용된다.

- 또한 Post Process Volume에서 Material을 추가한다.
6. Enemy 레벨에 배치한다.
- Enemy 클래스로 블루프린트를 생성한다.
- 메쉬를 적용하고 레벨에 배치한다.
3. 결과

'Unrael > Implement' 카테고리의 다른 글
| [UE/Implement] 미니 프로젝트 회고 (0) | 2025.02.13 |
|---|---|
| [UE/Basic] 치트 매니저 (Cheat Manager) (0) | 2025.02.12 |
| [UE/Implement] 트랩 구현 (0) | 2025.02.11 |
| [UE/Implement] 쿼터뷰 구현하기 (0) | 2024.12.31 |
| [UE/Implement] 키 입력으로 캐릭터 움직이기 (0) | 2024.12.30 |