OSWorlds - 게임 블로그 📌 게임 프로그래밍 📌 게임소식 🔑 로그인 📝 회원가입

언리얼 엔진 Blueprint Interface와 Cast To 차이

언리얼 엔진 블루프린트로 상호작용 기능을 만들다 보면 Cast To 노드를 자주 사용하게 됩니다.

문을 열 때도 Cast To, 적에게 공격을 전달할 때도 Cast To, 아이템을 획득할 때도 Cast To를 사용하다 보면 Event Graph 곳곳에 서로 다른 Cast 노드가 늘어나기 시작합니다.

이때 자주 추천되는 기능이 Blueprint Interface입니다. 하지만 Cast To를 모두 Interface로 바꿔야 하는지, 두 기능이 정확히 어떻게 다른지 몰라 더 혼란스러울 수 있습니다.

두 기능은 서로 경쟁하는 기능이 아닙니다. 상황에 따라 Cast To가 더 자연스러울 때도 있고, Blueprint Interface를 사용해야 구조가 깔끔해질 때도 있습니다.

이번 글에서는 문, 아이템, NPC와 상호작용하는 실제 게임 구조를 예로 들어 Blueprint Interface와 Cast To의 차이를 쉽게 알아보겠습니다.

💡 한 줄 정답 — Cast To는 현재 가지고 있는 Object가 내가 원하는 특정 클래스인지 확인한 뒤 그 클래스만 가진 변수와 함수에 접근할 때 사용하고, Blueprint Interface는 대상이 문인지 아이템인지 NPC인지 정확한 클래스를 몰라도 해당 대상이 약속된 기능을 구현했다면 같은 메시지를 전달할 때 사용합니다. 한 종류의 객체와 구체적으로 통신할 때는 Cast To가 편하고, 서로 다른 종류의 객체가 공통된 행동을 해야 한다면 Blueprint Interface가 더 잘 어울립니다.

목차

  1. 블루프린트 통신이 필요한 이유
  2. Cast To란 무엇인가?
  3. Blueprint Interface란 무엇인가?
  4. 두 기능의 차이 한눈에 보기
  5. Cast To가 필요한 상황
  6. Blueprint Interface가 필요한 상황
  7. 상호작용 시스템 만들기
  8. Interface Message가 실행되지 않는 이유
  9. Cast To를 많이 사용하면 느려질까?
  10. 초보자가 자주 하는 실수

블루프린트 통신은 왜 필요할까?

게임 안의 블루프린트는 혼자서만 작동하지 않습니다.

플레이어가 문 앞에서 상호작용 키를 누르면 Character가 문 블루프린트에 열리라는 신호를 보내야 합니다. 공격이 적에게 맞으면 무기나 전투 컴포넌트가 적에게 피해 정보를 전달해야 합니다.

상점 NPC와 대화할 때는 PlayerController가 NPC나 UI에 대화 시작을 요청할 수도 있습니다.

이처럼 한 블루프린트가 다른 블루프린트의 변수나 함수를 사용하려면 먼저 통신할 대상을 알아야 합니다. 이를 위해 가장 먼저 필요한 것이 Object Reference, 즉 객체 참조입니다.

Cast To와 Blueprint Interface 모두 대상 객체가 있어야 사용할 수 있습니다. Interface를 사용한다고 해서 대상 참조를 찾는 과정까지 자동으로 해결되는 것은 아닙니다.

예를 들어 Line Trace를 이용한 상호작용 시스템에서는 Hit Actor가 대상 참조가 됩니다. Overlap 이벤트에서는 Other Actor가 대상 참조가 될 수 있습니다.


Cast To란 무엇인가?

Cast To는 현재 가지고 있는 Object가 원하는 클래스인지 확인하는 기능입니다.

예를 들어 Get Player Character 노드의 반환값은 일반적인 Character 참조입니다. 하지만 프로젝트에서 만든 BP_MainCharacter만 가지고 있는 체력 회복 함수나 전투 컴포넌트에 접근하려면 더 구체적인 타입이 필요합니다.

이때 Cast To BP_MainCharacter를 사용합니다.

캐스트에 성공하면 대상이 실제로 BP_MainCharacter이거나 해당 클래스를 상속한 자식 클래스라는 뜻입니다. As BP Main Character 핀을 통해 해당 클래스의 변수와 함수를 사용할 수 있습니다.

반대로 대상이 전혀 다른 클래스라면 Cast Failed가 실행됩니다.

Cast To는 객체를 찾는 노드가 아니다

초보자가 가장 자주 오해하는 부분입니다.

Cast To는 월드 안에서 해당 객체를 찾아 주지 않습니다. Cast의 Object 핀에는 이미 가져온 참조를 넣어야 합니다.

다음과 같은 참조가 Cast의 Object 핀에 연결될 수 있습니다.

  • Get Player Character의 반환값
  • Get Player Controller의 반환값
  • Line Trace의 Hit Actor
  • Overlap 이벤트의 Other Actor
  • Spawn Actor의 Return Value
  • 미리 저장해 둔 Actor Reference

참조 자체가 None이라면 Cast도 성공할 수 없습니다.

Epic Games 공식 문서에서도 Actor의 변수나 함수에 접근하려면 먼저 올바른 참조를 확보해야 하며, 런타임에 생성되는 객체를 특정 블루프린트 타입으로 다룰 때 Cast To를 사용할 수 있다고 설명합니다. Referencing Actors 공식 문서


Blueprint Interface란 무엇인가?

Blueprint Interface는 서로 다른 블루프린트가 공통으로 사용할 함수의 이름과 입력값, 출력값을 정의하는 기능입니다.

쉽게 말하면 “이 Interface를 추가한 객체는 이 메시지를 받을 수 있다”라는 약속을 만드는 것입니다.

예를 들어 BPI_Interact라는 Blueprint Interface를 만들고 Interact 함수를 추가했다고 가정해 보겠습니다.

다음과 같이 서로 다른 블루프린트에 같은 Interface를 추가할 수 있습니다.

  • 문 블루프린트
  • 아이템 블루프린트
  • 상점 NPC
  • 보물상자
  • 스위치
  • 탑승 가능한 차량

플레이어는 대상의 정확한 클래스가 무엇인지 몰라도 Interact 메시지를 보낼 수 있습니다.

문은 메시지를 받으면 문을 열고, 아이템은 인벤토리에 들어가며, NPC는 대화를 시작합니다. 같은 메시지를 받았지만 실제 행동은 각 블루프린트가 다르게 구현합니다.

Blueprint Interface에는 실제 동작이 들어 있지 않다

Blueprint Interface에는 함수의 이름과 필요한 입출력 정보만 정의합니다.

실제로 문을 회전하거나 아이템을 제거하는 로직은 해당 Interface를 구현한 각각의 블루프린트에 작성해야 합니다.

Blueprint Interface에는 일반 블루프린트와 달리 다음 항목을 추가할 수 없습니다.

  • 새로운 변수
  • 컴포넌트
  • 일반 Event Graph 구현
  • 자체 상태를 저장하는 로직

Epic Games 공식 문서는 Blueprint Interface를 구현 내용 없이 함수 이름을 정의하는 모음으로 설명합니다. Interface를 추가한 각 블루프린트가 해당 함수의 실제 동작을 따로 구현합니다. Blueprint Interface 개요


Blueprint Interface는 어떻게 추가할까?

콘텐츠 브라우저에서 마우스 오른쪽 버튼을 누른 뒤 다음 순서로 Blueprint Interface를 만들 수 있습니다.

Add → Blueprints → Blueprint Interface

이름은 다른 블루프린트와 쉽게 구분할 수 있도록 BPI_ 접두사를 붙이는 편이 좋습니다.

예를 들면 다음과 같습니다.

  • BPI_Interact
  • BPI_Damageable
  • BPI_Targetable
  • BPI_Saveable

BPI_Interact를 열고 Interact라는 함수를 추가합니다. 필요한 경우 Interactor나 InteractionType 같은 입력값도 만들 수 있습니다.

Interface를 사용할 문이나 아이템 블루프린트를 연 뒤 다음 위치에서 추가합니다.

Class Settings → Interfaces → Implemented Interfaces → Add

Interface를 추가하고 컴파일하면 My Blueprint 패널의 Interfaces 영역에 함수가 나타납니다.

함수에 출력값이 없다면 Event Graph에서 Interface Event로 구현할 수 있습니다. 출력값이 있는 Interface 함수는 일반 함수 형태로 표시될 수 있으므로, 이벤트 목록에 나타나지 않는다고 해서 오류는 아닙니다.


Blueprint Interface와 Cast To 차이 한눈에 보기

구분Cast ToBlueprint Interface
주요 목적특정 클래스인지 확인공통 기능 호출
대상 클래스 정보구체적인 클래스를 알아야 함구체적인 클래스를 몰라도 됨
접근 범위대상 클래스의 변수와 함수Interface에 선언한 함수
실패 처리Cast Failed 핀 제공Message 호출은 대상이 미구현 시 동작하지 않음
결합 정도특정 클래스에 의존클래스 간 의존을 줄일 수 있음
적합한 상황플레이어 캐릭터, 특정 보스문, 아이템, NPC 등 공통 상호작용
구현 방식호출하는 쪽에서 클래스 확인받는 객체마다 동작을 따로 구현

가장 중요한 차이는 상대방의 구체적인 클래스까지 알아야 하는가입니다.

BP_BossCharacter만 가지고 있는 BossPhase 값을 가져와야 한다면 Cast To가 자연스럽습니다.

반대로 눈앞의 대상이 문인지 상자인지 NPC인지 상관없이 상호작용만 요청하고 싶다면 Blueprint Interface가 더 잘 어울립니다.


Cast To가 더 편한 상황

Cast To가 나쁜 기능이라고 생각해 무조건 피할 필요는 없습니다. 대상이 명확하고 해당 클래스의 고유한 기능이 필요하다면 Cast To가 가장 이해하기 쉬운 방법일 수 있습니다.

플레이어 캐릭터의 고유 기능에 접근할 때

PlayerController에서 현재 Pawn을 가져온 뒤 프로젝트의 실제 캐릭터 클래스로 변환해야 한다면 Cast To를 사용할 수 있습니다.

예를 들어 다음 기능은 특정 Character 클래스에만 있을 수 있습니다.

  • Combat Component 가져오기
  • 플레이어 전용 스킬 실행
  • 플레이어 체력 UI 갱신
  • 인벤토리 컴포넌트 접근
  • 플레이어 전용 상태 확인

특정 보스의 전용 변수에 접근할 때

현재 적이 일반 Enemy가 아니라 BP_BossCharacter인지 확인하고 보스 페이즈나 QTE 상태를 가져와야 한다면 Cast To가 적합할 수 있습니다.

한 번 확인한 참조를 저장할 때

BeginPlay나 초기화 시점에 한 번 Cast한 뒤 성공한 참조를 변수로 저장해 두는 방식도 자주 사용됩니다.

같은 대상을 사용할 때마다 반복해서 Cast하는 것보다 유효한 참조를 저장하고 필요할 때 사용하는 편이 Event Graph를 읽기 쉽습니다.


Blueprint Interface가 더 편한 상황

Blueprint Interface는 서로 상속 관계가 없는 여러 객체에 같은 요청을 보내야 할 때 특히 편리합니다.

여러 종류의 상호작용 객체

문, 레버, 보물상자, NPC는 서로 다른 클래스입니다. Cast To만 사용한다면 다음처럼 대상마다 Cast를 이어 붙여야 할 수 있습니다.

Cast To Door → 실패 → Cast To Item → 실패 → Cast To NPC

상호작용 객체가 추가될 때마다 플레이어 블루프린트도 수정해야 합니다.

하지만 모든 대상이 BPI_Interact를 구현한다면 플레이어는 Hit Actor에 Interact Message만 보내면 됩니다. 나중에 새로운 자판기나 엘리베이터를 추가해도 플레이어 블루프린트를 다시 수정할 필요가 없습니다.

여러 객체가 같은 피해 메시지를 받을 때

적 캐릭터, 파괴 가능한 상자, 훈련용 허수아비가 모두 공격에 반응해야 한다면 BPI_Damageable 같은 Interface를 사용할 수 있습니다.

각 객체는 같은 ReceiveHit 메시지를 받지만 결과는 다르게 처리할 수 있습니다.

  • 적 캐릭터: 체력 감소
  • 상자: 내구도 감소 후 파괴
  • 허수아비: 피해 숫자만 표시
  • 방패: 공격 차단 효과 재생

공식 문서에서도 자동차와 나무처럼 전혀 다른 객체가 같은 공격 메시지를 받아 각자 다르게 반응하는 사례로 Blueprint Interface를 설명합니다. Blueprint Interface 구현 공식 문서


Blueprint Interface로 상호작용 시스템 만들기

HTML Anchor: interaction-system

이번에는 플레이어가 바라보는 문, 아이템, NPC와 상호작용하는 구조를 만들어 보겠습니다.

1. BPI_Interact 생성하기

Blueprint Interface를 생성하고 이름을 BPI_Interact로 지정합니다.

Interface 안에 다음 함수를 추가합니다.

  • 함수 이름: Interact
  • 입력값: Interactor
  • 입력값 타입: Actor Object Reference

Interactor에는 상호작용을 요청한 플레이어나 캐릭터 참조가 전달됩니다.

2. 상호작용 객체에 Interface 추가하기

문 블루프린트인 BP_Door를 열고 Class Settings에서 BPI_Interact를 추가합니다.

같은 방법으로 다음 블루프린트에도 Interface를 추가할 수 있습니다.

  • BP_PickupItem
  • BP_NPC
  • BP_TreasureChest

3. 각 객체에서 Interact 구현하기

BP_Door의 Interact Event에서는 문을 여는 Timeline을 실행합니다.

BP_PickupItem에서는 아이템을 인벤토리에 추가한 뒤 월드의 아이템을 제거합니다.

BP_NPC에서는 대화 UI를 표시합니다.

같은 Interact 메시지를 받지만 각 객체의 역할에 따라 서로 다른 로직이 실행됩니다.

4. 플레이어가 바라보는 객체 찾기

플레이어 Character 또는 PlayerController에서 Line Trace를 실행합니다.

Line Trace에 성공하면 Break Hit Result를 통해 Hit Actor를 가져옵니다. 이 Hit Actor가 실제 메시지를 받을 대상입니다.

5. Interact Message 호출하기

Hit Actor를 Interact (Message) 노드의 Target에 연결합니다. Interactor에는 플레이어 Character의 참조를 전달합니다.

이제 대상이 BPI_Interact를 구현했다면 해당 객체의 Interact 로직이 실행됩니다.


Interface Message가 실행되지 않는 이유

Interface를 만들고 Message 노드를 호출했는데 아무 반응이 없을 때가 있습니다. 이 경우 다음 항목을 차례대로 확인해 보세요.

대상 블루프린트에 Interface를 추가하지 않았다

Interface 파일을 만드는 것만으로는 사용할 수 없습니다. 메시지를 받을 블루프린트의 Class Settings에서 Interface를 직접 추가해야 합니다.

Interface를 추가한 뒤 컴파일하지 않았다

Implemented Interfaces에 추가했다면 Compile과 Save를 실행합니다. 다른 블루프린트에서 노드가 검색되지 않는다면 관련 블루프린트를 다시 컴파일해 보는 것도 좋습니다.

Target에 잘못된 객체가 들어갔다

Interface Message의 Target에는 실제로 메시지를 받을 객체 참조가 들어가야 합니다.

Line Trace를 사용한다면 Hit Component가 아니라 Hit Actor가 필요한 상황인지 확인합니다. Actor Component가 Interface를 구현했다면 반대로 해당 Component 참조를 Target으로 전달해야 합니다.

함수 이름만 만들고 실제 동작을 구현하지 않았다

Interface에 Interact 함수를 만든 뒤 문이나 아이템 블루프린트에서 해당 함수를 구현하지 않으면 눈에 보이는 동작은 일어나지 않습니다.

대상이 Interface를 구현했는지 확인하지 않았다

필요하다면 Does Implement Interface 노드를 사용해 대상이 해당 Interface를 구현했는지 먼저 확인할 수 있습니다.

Message 방식은 대상이 Interface를 구현하지 않았을 때 Cast Failed처럼 별도의 실패 실행 핀을 제공하지 않습니다. 실패 상황에 다른 처리가 필요하다면 Does Implement Interface 또는 유효성 검사를 함께 사용하는 것이 좋습니다.


Cast To를 많이 사용하면 게임이 느려질까?

“Cast To는 성능이 나쁘기 때문에 사용하면 안 된다”라는 말을 종종 볼 수 있습니다. 하지만 Cast 노드 하나를 사용했다고 게임 성능이 바로 나빠지는 것은 아닙니다.

런타임에서 객체 타입을 확인하는 캐스트 자체보다 더 주의해야 할 부분은 다음과 같습니다.

  • Tick에서 매 프레임 반복하는 Cast
  • 같은 대상을 사용할 때마다 다시 실행하는 Cast
  • 필요 이상으로 이어진 Cast Failed 구조
  • 서로 다른 대형 블루프린트를 직접 참조하는 구조
  • 특정 클래스에 지나치게 강하게 의존하는 설계

블루프린트 클래스끼리 직접 참조하면 에셋 간 의존 관계가 생길 수 있습니다. 참조 구조가 복잡해지면 하나의 블루프린트를 불러올 때 관련 에셋까지 함께 로드되는 범위가 커질 수 있습니다.

따라서 Cast To를 무조건 제거하기보다 다음 기준으로 판단하는 것이 좋습니다.

  • 대상이 명확하고 클래스 고유 기능이 필요하다면 Cast To
  • 여러 종류의 객체에 공통 메시지를 보내려면 Interface
  • 자주 사용하는 참조라면 한 번 Cast한 뒤 변수에 저장
  • 매 프레임 실행할 필요가 없다면 이벤트 방식으로 변경

Blueprint Interface를 사용해도 Cast가 필요한 경우

Interface를 사용한다고 해서 프로젝트에서 Cast To가 완전히 사라지는 것은 아닙니다.

예를 들어 Interact 메시지의 입력값으로 Actor Reference를 전달했다고 가정해 보겠습니다. 문 블루프린트는 단순히 열리기만 하면 되기 때문에 플레이어의 구체적인 클래스가 필요하지 않을 수 있습니다.

하지만 아이템 블루프린트가 플레이어의 특정 Inventory Component에 직접 접근해야 한다면 전달받은 Interactor를 BP_MainCharacter로 Cast해야 할 수도 있습니다.

이 경우 다음과 같이 역할을 나눌 수 있습니다.

  • 상호작용 요청 전달: Blueprint Interface
  • 플레이어 전용 기능 접근: Cast To

둘 중 하나만 사용해야 하는 것이 아니라 필요한 위치에서 함께 사용할 수 있습니다.

더 좋은 구조를 원한다면 플레이어 Character도 별도의 Inventory Interface를 구현하도록 만들어 아이템과 플레이어 사이의 직접적인 클래스 의존성을 줄이는 방법도 있습니다.


초보자가 자주 하는 실수

Cast To만 하면 대상 객체가 생긴다고 생각한다

Cast는 참조를 생성하거나 검색하지 않습니다. 먼저 올바른 Object Reference를 가져와야 합니다.

Cast Failed를 연결하지 않는다

Cast 실패가 정상적으로 발생할 수 있는 구조라면 Cast Failed에서 예외 처리를 해주는 것이 좋습니다. 디버깅 중에는 Print String을 연결해 실패 원인을 확인할 수도 있습니다.

모든 블루프린트를 Interface로 바꾸려고 한다

항상 특정 플레이어 캐릭터만 사용하는 기능이라면 Cast To가 오히려 읽기 쉽습니다. Interface가 구조를 무조건 더 좋게 만드는 것은 아닙니다.

Interface에 공통 로직까지 넣으려고 한다

Blueprint Interface에는 함수의 약속만 정의합니다. 공통 구현이 필요하다면 부모 클래스, Actor Component 또는 Blueprint Function Library가 더 적합할 수 있습니다.

Target을 비워 둔다

Interface Message도 Target이 필요합니다. Target이 None이거나 다른 객체라면 원하는 이벤트가 실행되지 않습니다.

Interface Event 이름을 직접 만든다

같은 이름의 Custom Event를 새로 만드는 것이 아니라, Interface를 구현한 뒤 Event Graph에서 해당 Interface Event를 추가해야 합니다.


Cast To와 Interface를 선택하는 가장 쉬운 기준

어떤 기능을 선택해야 할지 헷갈린다면 다음 질문을 순서대로 해보세요.

특정 클래스의 변수나 함수가 필요한가?

그렇다면 Cast To가 적합합니다.

예를 들어 BP_BossCharacter의 CurrentBossPhase를 가져와야 한다면 대상의 구체적인 클래스가 필요합니다.

서로 다른 객체에 같은 요청을 보낼 것인가?

그렇다면 Blueprint Interface가 적합합니다.

문, 아이템, NPC에 모두 Interact를 전달해야 한다면 Interface를 사용하는 편이 깔끔합니다.

한 객체의 변화를 여러 객체에 알릴 것인가?

이 경우에는 Blueprint Interface보다 Event Dispatcher가 더 잘 어울릴 수 있습니다.

예를 들어 보스가 사망했을 때 문, UI, 음악 시스템이 동시에 반응해야 한다면 Event Dispatcher의 일대다 통신 구조를 고려할 수 있습니다.

상황추천 방식
특정 플레이어 클래스에 접근Cast To
문·아이템·NPC 공통 상호작용Blueprint Interface
보스 사망을 여러 객체에 알림Event Dispatcher
이미 알고 있는 특정 Actor와 통신Direct Reference
공통 기능과 데이터 구현 공유부모 클래스 또는 Actor Component

마무리

Cast To와 Blueprint Interface의 차이는 상대방의 구체적인 클래스를 알아야 하는지 생각하면 쉽게 구분할 수 있습니다.

Cast To는 현재 참조가 원하는 클래스인지 확인하고, 그 클래스만 가진 변수와 함수에 접근하기 위한 기능입니다. Blueprint Interface는 서로 다른 클래스가 같은 메시지를 받을 수 있도록 공통된 약속을 만드는 기능입니다.

특정 플레이어나 보스의 고유한 기능에 접근한다면 Cast To가 편합니다. 문, 아이템, NPC처럼 종류는 다르지만 모두 상호작용해야 하는 객체라면 Blueprint Interface가 더 잘 어울립니다.

Cast To를 무조건 나쁜 기능으로 생각하거나 모든 통신을 Interface로 바꿀 필요는 없습니다. 프로젝트의 기능과 객체 관계에 맞춰 두 방식을 적절하게 섞어 사용하는 것이 가장 중요합니다.

다음 글에서는 한 객체에서 발생한 사건을 여러 객체에 전달할 때 유용한 Blueprint Event Dispatcher 사용법을 보스 사망, 문 열림, UI 갱신 사례와 함께 알아보겠습니다.


참고 사이트

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤