직접 참조를 통한 블루프린트 통신
블루프린트로 게임을 개발하다 보면, 서로 다른 블루프린트들이 정보를 주고받거나 특정 기능을 호출해야 하는 경우가 빈번하게 발생합니다. 예를 들어, 플레이어 캐릭터 블루프린트가 문 블루프린트에게 "열려라"는 명령을 내리거나, 폭발 블루프린트가 주변의 모든 적 블루프린트에게 "대미지를 받아라"는 신호를 보내는 것과 같습니다. 이처럼 블루프린트 간에 상호작용하는 방법을 블루프린트 통신(Blueprint Communication) 이라고 합니다.
이번 절에서는 가장 기본적인 블루프린트 통신 방법인 직접 참조(Direct Reference)를 통한 통신에 대해 알아보겠습니다.
직접 참조란 무엇인가?
직접 참조는 특정 블루프린트가 다른 특정 블루프린트 인스턴스에 대한 직접적인 연결(포인터) 을 가지는 것을 의미합니다. 마치 여러분이 친구의 집 주소를 정확히 알고 찾아가는 것과 같습니다. 주소를 알면 그 친구의 집을 직접 방문하여 원하는 요청을 할 수 있죠.
언리얼 엔진에서 직접 참조는 주로 변수(Variable) 를 통해 이루어집니다. 어떤 블루프린트가 다른 블루프린트 타입의 변수를 가지면, 그 변수에 특정 블루프린트 인스턴스를 할당하여 직접적인 연결을 만들 수 있습니다.
직접 참조를 통한 통신 과정
직접 참조를 이용한 블루프린트 통신은 다음과 같은 단계로 이루어집니다.
-
참조할 대상 블루프린트의 변수 생성
- 통신을 시작할 블루프린트(예:
BP_PlayerCharacter
)를 엽니다. - 변수 패널에서 새 변수를 추가합니다.
- 변수 유형(Variable Type) 을 참조하고 싶은 블루프린트 클래스(예:
BP_Door
타입의Object Reference
)로 설정합니다. 이렇게 하면 이 변수는BP_Door
타입의 액터 인스턴스를 담을 수 있게 됩니다. 변수 이름은TargetDoor
와 같이 설정할 수 있습니다.
- 통신을 시작할 블루프린트(예:
-
참조할 인스턴스에 변수 값 할당 이것이 직접 참조 통신에서 가장 중요한 단계입니다. 변수를 만들었다고 해서 자동으로 연결되는 것이 아니라, 특정 월드에 존재하는 액터 인스턴스를 그 변수에 '할당'해주어야 합니다. 할당하는 방법은 여러 가지가 있습니다.
-
수동 할당 (디테일 패널)
BP_PlayerCharacter
블루프린트 에디터에서TargetDoor
변수를 선택합니다.- 디테일 패널에서
인스턴스 편집 가능(Instance Editable)
옵션을 체크합니다. (또는 눈 아이콘을 클릭하여 열린 눈 형태로 만듭니다.) 이렇게 하면 이 변수가 월드에 배치된BP_PlayerCharacter
인스턴스에서 직접 편집 가능해집니다. - 메인 언리얼 에디터로 돌아와 월드에 배치된
BP_PlayerCharacter
액터를 선택합니다. - 디테일 패널을 살펴보면
TargetDoor
변수가 보일 것입니다. 이 변수 옆의 드롭다운을 클릭하거나, 스포이드 아이콘을 클릭하여 월드에 배치된 특정BP_Door
액터 인스턴스를 직접 선택하거나, 월드 아웃라이너에서 해당 액터를 드래그하여 변수 칸에 놓을 수 있습니다. - 장점: 가장 간단하고 명확하게 특정 액터 인스턴스와 연결할 수 있습니다.
- 단점: 매번 수동으로 연결해야 하므로, 오브젝트가 많거나 동적으로 생성되는 경우에는 비효율적입니다.
-
동적 할당 (블루프린트 로직)
BeginPlay
시점에 찾기: 게임 시작 시점에 특정 타입의 액터를 찾아 변수에 할당합니다.Event BeginPlay
뒤에Get All Actors Of Class
노드를 추가합니다.Actor Class
핀에BP_Door
를 선택합니다.- 이 노드는 월드에 있는 모든
BP_Door
액터 배열을 반환합니다. 만약 문이 하나뿐이거나 첫 번째 문만 필요하다면, 배열의 첫 번째 요소(Get (a copy)
)를 가져와Set TargetDoor
노드에 연결합니다. - 장점: 코드로 동적으로 연결되므로 수동 설정이 필요 없습니다.
- 단점: 특정 태그(Tag)나 이름(Name)을 사용하지 않으면 정확한 인스턴스를 찾기 어렵거나, 여러 개 중 의도치 않은 것이 선택될 수 있습니다.
Overlap
이벤트 시 할당: 플레이어가 문과 겹쳤을 때 해당 문을TargetDoor
변수에 할당하는 방식입니다.- 플레이어 캐릭터 블루프린트에
Sphere Collision
컴포넌트를 추가합니다. Sphere Collision
의OnComponentBeginOverlap
이벤트를 생성합니다.- 이벤트의
Other Actor
핀을Cast To BP_Door
노드에 연결하여Other Actor
가BP_Door
타입인지 확인합니다. Cast To BP_Door
노드의As BP Door
출력 핀을Set TargetDoor
노드의 입력 핀에 연결합니다. (성공적으로 캐스팅되었을 때만 실행되도록Cast
노드의 성공 실행 핀을 연결)- 장점: 플레이어와 상호작용하는 대상을 동적으로 참조할 수 있습니다.
- 단점: 충돌이나 특정 조건이 발생했을 때만 연결이 이루어집니다.
- 플레이어 캐릭터 블루프린트에
-
-
참조된 변수를 통해 기능 호출
TargetDoor
변수에BP_Door
인스턴스가 성공적으로 할당되었다면, 이제 이 변수를 통해BP_Door
블루프린트 내부의 함수나 변수에 접근할 수 있습니다.- 예를 들어, 플레이어 캐릭터 블루프린트에서
E
키를 눌렀을 때TargetDoor
를 열고 싶다면:Event E
키 입력 노드를 추가합니다.TargetDoor
변수(Get 노드)를 가져옵니다.TargetDoor
변수 노드의 출력 핀에서 드래그하여OpenDoor
함수(BP_Door에 정의된 함수)를 검색하고 호출합니다.Event E
키의 실행 핀을OpenDoor
함수의 실행 핀에 연결합니다.
직접 참조의 장점과 단점
-
장점
- 직관적이고 간단합니다: 특정 오브젝트에 직접적으로 접근하므로 로직 이해가 쉽습니다.
- 성능 효율적: 한 번 참조가 설정되면, 직접적인 메모리 주소를 통해 접근하므로 빠르게 호출됩니다.
-
단점
- 강한 결합(Tight Coupling): 호출하는 블루프린트(예: 플레이어)가 호출되는 블루프린트(예: 문)의 특정 클래스 타입(BP_Door)을 직접적으로 알아야 합니다. 이는 나중에 문 대신 다른 종류의 상호작용 오브젝트(예: 레버)를 추가하려면 플레이어 블루프린트의 로직을 수정해야 할 수도 있다는 의미입니다.
- 유연성 부족: 동적으로 생성되거나 사라지는 오브젝트, 혹은 여러 종류의 오브젝트에 공통적으로 적용하기 어렵습니다.
- 안정성 문제: 만약
TargetDoor
변수에 유효한 액터가 할당되지 않은 상태에서 함수를 호출하면,Access None
오류가 발생하여 게임이 멈추거나 오작동할 수 있습니다. (이것이 가장 큰 단점이며, 이를 방지하기 위해IsValid
노드를 통해 유효성 검사를 하는 것이 좋습니다.)
직접 참조는 간단한 통신에는 효과적이지만, 대규모 프로젝트나 복잡한 시스템에서는 Access None
오류와 같은 문제로 인해 유지보수가 어려워질 수 있습니다.