이 하우투 튜토리얼에서는 스프링 암 컴포넌트를 추가하고 카메라 컴포넌트(Camera Component) 의 부모로 지정할 것입니다. 스프링 암 컴포넌트는 카메라가 게임플레이 상황에 따라 늘어나거나 줄어들 수 있게 합니다. 삼인칭 시점을 만들기 위해 캐릭터에 카메라를 추가하는 경우가 많은데, 이때 일반적으로는 스프링 암을 포함하여 카메라가 레벨 지오메트리나 기타 오브젝트에 방해받는 상황을 처리하는 방법을 자동으로 제어하는 것이 권장됩니다.
이 하우투 튜토리얼에서는 스프링 암 컴포넌트 (USpringArmComponent)를 추가하고 카메라 컴포넌트(Camera Component) 의 부모로 지정할 것입니다. 스프링 암 컴포넌트는 카메라가 게임플레이 상황에 따라 늘어나거나 줄어들 수 있게 합니다. 삼인칭 시점을 만들기 위해 캐릭터에 카메라를 추가하는 경우가 많은데, 이때 일반적으로는 스프링 암을 포함하여 카메라가 레벨 지오메트리나 기타 오브젝트에 방해받는 상황을 처리하는 방법을 자동으로 제어하는 것이 권장됩니다.

이 튜토리얼에는 카메라 컴포넌트가 할당된 것이면 어떤 캐릭터든 사용해도 좋습니다. 캐릭터가 없는 경우, 여기서 사용되는 기본 캐릭터 생성을 위해 []((making-interactive-experiences/interactive-framework/camera/using-cameras/CameraComponents) 튜토리얼 먼저 진행해보는 것이 좋습니다.
카메라가 레벨의 오브젝트를 관통하게 되는 경우를 완전히 없앨 수는 없겠지만, 스프링 암의 설정에 따라 무언가에 방해를 받을 때는 카메라 위치를 자동으로 옮겼다가 더이상 방해받지 않게 되면 원래 위치로 되돌리도록 하여, 부작용을 최소화시키는 데 도움이 될 것입니다.
스프링 암 컴포넌트 생성
-
카메라 컴포넌트로 작업하기 하우투 튜토리얼 프로젝트에서 계속하여 BP_CameraCharacter 블루프린트를 엽니다.
-
컴포넌트(Components) 탭에서 컴포넌트 추가(Add Component) 버튼을 클릭한 다음 스프링 암 컴포넌트(Spring Arm Component) 를 검색하고 선택합니다. 컴포넌트 이름을 SpringArmComp 로 변경합니다.
-
컴포넌트(Components) 탭에서 CameraComp 컴포넌트를 스프링 암 컴포넌트(Spring Arm Component) 위로 드래그하여 어태치합니다.
-
컴포넌트(Components) 탭에서 SpringArmComp 를 선택한 상태로 디테일(Details) 패널로 이동합니다. 스프링 암 컴포넌트(Spring Arm Component) 와 함께 사용 가능한 세팅은 다음과 같습니다.
섹션 설명 소켓(Sockets) 스프링 암을 스켈레탈 메시(Skeletal Mesh) 의 본(Bone) 또는 소켓(Socket) 의 부모로 지정합니다. 카메라(Camera) 콜리전이 없는 경우 스프링 암의 길이와 오프셋(Offsets) 을 설정합니다. 카메라 콜리전(Camera Collision) 콜리전 검사 여부를 설정하고 콜리전을 검사할 쿼리 프로브의 크기를 정의합니다. 카메라 세팅(Camera Settings) 피치(Pitch), 요(Yaw), 롤(Roll) 을 부모로부터 상속할지 아니면 폰 제어 회전 사용(Use Pawn Control Rotation) 에 따를지 설정합니다. 렉(Lag) 카메라가 타깃 위치보다 뒤처질지 여부 및 렉 관련 세팅을 설정합니다. -
트랜스폼(Transform) 카테고리에서 위치(Location) 값을 (0, 0, 150)으로, 회전(Rotation) 값을 (0, 0, 90)으로 변경합니다.
-
카메라 세팅(Camera Settings) 카테고리에서 폰 제어 회전 사용(Use Pawn Control Rotation) 변수 옆의 체크박스를 클릭합니다. 활성화하면 스프링 암 컴포넌트(Spring Arm Component) 의 부모가 CameraCharacter 폰의 뷰와 컨트롤을 사용합니다.
-
렉(Lag) 카테고리에서 카메라 렉 활성화(Enable Camera Lag) 변수 옆의 체크박스를 클릭합니다. 활성화하면 카메라가 타깃 위치보다 뒤처지면서 움직임이 더 부드러워집니다.
-
카메라 컴포넌트로 작업하기 하우투 튜토리얼 프로젝트에서 계속하여
CameraCharacter.h를 열고 클래스 정의에서 다음을 선언합니다.UPROPERTY(EditDefaultsOnly,BlueprintReadWrite) class USpringArmComponent* SpringArmComp; -
그런 다음
CameraCharacter.cpp로 이동하여 아래의 클래스 라이브러리를 포함합니다.#include "GameFramework/SpringArmComponent.h" -
다음으로 ACameraCharacter::ACameraCharacter 생성자에서 다음 코드를 선언합니다.
//클래스 컴포넌트 인스턴스화 SpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArmComp")); //스프링 암을 캐릭터의 스켈레탈 메시 컴포넌트에 어태치 SpringArmComp->SetupAttachment(GetMesh()); //카메라를 스프링 암 컴포넌트에 어태치 CameraComp->AttachToComponent(SpringArmComp, FAttachmentTransformRules::KeepRelativeTransform); //SpringArmComp의 디폴트 프로퍼티 세팅 SpringArmComp->bUsePawnControlRotation = true; SpringArmComp->bEnableCameraLag = true; SpringArmComp->TargetArmLength = 300.0f; -
코드를 컴파일(Compile) 합니다.
-
콘텐츠 브라우저(Content Browser) 에서 BP_CameraCharacter 를 더블클릭하여 클래스 디폴트(Class Defaults) 를 연 다음, 컴포넌트(Components) 탭에서SpringArmComp 를 선택합니다.
스프링 암 컴포넌트와 함께 사용 가능한 세팅을 요약하면 다음과 같습니다.
/** 스프링 암 끝에서 스프링 암 원점을 향하는 소켓의 이름 */ static const FName SocketName; /** 콜리전이 없는 경우 스프링 암의 기본 길이 */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Camera) float TargetArmLength; /** 스프링 암 끝 오프셋. 라인 트레이스가 의도한 대로 작동하게 하려면 어태치된 컴포넌트의 상대 오프셋 대신 이 값을 사용합니다 */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Camera) FVector SocketOffset; /** 스프링 시작 오프셋. 월드 스페이스에 적용합니다. 일반적인 상대 스페이스 오프셋 대신 부모 컴포넌트의 월드 스페이스 오프셋을 원하는 경우 사용합니다. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Camera) FVector TargetOffset; /** 쿼리 프로브 스피어 크기(단위는 언리얼 유닛) */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraCollision, meta=(editcondition="bDoCollisionTest")) float ProbeSize; /** 쿼리 프로브의 콜리전 채널(디폴트는 ECC_Camera) */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraCollision, meta=(editcondition="bDoCollisionTest")) TEnumAsByte<ECollisionChannel> ProbeChannel; /** true인 경우 카메라가 레벨로 클리핑되는 것을 방지하기 위해 ProbeChannel 및 ProbeSize를 사용하여 콜리전 테스트를 실시합니다. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraCollision) uint32 bDoCollisionTest:1; /**이 컴포넌트가 폰에 배치된 경우, 가능하면 폰의 뷰/컨트롤 회전을 사용할지 여부입니다. * 비활성화되면 컴포넌트는 저장된 상대 회전으로 되돌아갑니다.**/ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraSettings) uint32 bUsePawnControlRotation:1; /** 부모 컴포넌트로부터 피치를 상속할지 여부입니다. 절대 회전을 사용하는 경우 아무것도 하지 않습니다. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraSettings) uint32 bInheritPitch : 1; /** 부모 컴포넌트로부터 요를 상속할지 여부입니다. 절대 회전을 사용하는 경우 아무것도 하지 않습니다. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraSettings) uint32 bInheritYaw : 1; /** 부모 컴포넌트로부터 롤을 상속할지 여부입니다. 절대 회전을 사용하는 경우 아무것도 하지 않습니다. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraSettings) uint32 bInheritRoll : 1; /** * true인 경우 카메라가 타깃 위치보다 뒤처지면서 움직임이 더 부드러워집니다. * @CameraLagSpeed 참조 */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag) uint32 bEnableCameraLag : 1; /** * true인 경우 카메라가 타깃 회전보다 뒤처지면서 움직임이 더 부드러워집니다. * @CameraRotationLagSpeed 참조 */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag) uint32 bEnableCameraRotationLag : 1; /** * bUseCameraLagSubstepping이 true인 경우 카메라 댐핑을 서브스텝핑하여 유동적인 프레임 레이트도 처리하게 합니다(비용이 발생할 수 있습니다). * @see CameraLagMaxTimeStep */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Lag, AdvancedDisplay) uint32 bUseCameraLagSubstepping : 1; /** * true이고 카메라 위치 렉이 활성화된 경우, 카메라 타깃(녹색)과 렉이 적용된 위치(노란색)에 마커를 그립니다. * 두 위치 사이에 선을 그립니다. 일반적으로는 녹색이지만, CameraLagMaxDistance에 의해 렉 타깃까지의 거리가 범위제한되는 경우 빨간색입니다. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag) uint32 bDrawDebugLagMarkers : 1; /** bEnableCameraLag이 true인 경우, 카메라가 타깃 위치에 얼마나 빨리 도달하는지 제어합니다. 값이 낮으면 렉이 증가하여 느려지고, 값이 높으면 렉이 감소하여 빨라지고, 0이면 렉 없이 즉시 도달합니다. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag, meta=(editcondition="bEnableCameraLag", ClampMin="0.0", ClampMax="1000.0", UIMin = "0.0", UIMax = "1000.0")) float CameraLagSpeed; /** bEnableCameraRotationLag이 true인 경우 카메라가 타깃 위치에 얼마나 빨리 도달하는지 제어합니다. 값이 낮으면 렉이 증가하여 느려지고, 값이 높으면 렉이 감소하여 빨라지고, 0이면 렉 없이 즉시 도달합니다. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag, meta=(editcondition = "bEnableCameraRotationLag", ClampMin="0.0", ClampMax="1000.0", UIMin = "0.0", UIMax = "1000.0")) float CameraRotationLagSpeed; /** 카메라 렉 서브스테핑 시 사용되는 최대 시간 스텝입니다. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Lag, AdvancedDisplay, meta=(editcondition = "bUseCameraLagSubstepping", ClampMin="0.005", ClampMax="0.5", UIMin = "0.005", UIMax = "0.5")) float CameraLagMaxTimeStep; /** 카메라 타깃이 렉으로 현재 위치에서 뒤처질 수 있는 최대 거리입니다. 0으로 설정하면 최대 거리가 적용되지 않습니다. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Lag, meta=(editcondition="bEnableCameraLag", ClampMin="0.0", UIMin = "0.0")) float CameraLagMaxDistance;
캐릭터 입력 설정
새로 구현한 스프링 암 컴포넌트의 기능을 시연하려면 캐릭터 클래스에 이동 입력을 추가해야 합니다.
-
우선 편집(Edit) > 프로젝트 세팅(Project Settings) > 엔진(Engine) > 입력(Input) 으로 이동한 다음, 바인딩(Bindings) 카테고리에서 축 매핑(Axis Mappings) 옆의 + 기호를 클릭하여 새 축 매핑을 생성합니다.
-
새 축 매핑을 MoveForward 로 명명한 다음 드롭다운 키 매핑 메뉴에서 W 를 검색하고 선택합니다.
-
MoveForward 축 매핑 옆의 + 기호를 클릭하여 키를 추가합니다. 드롭다운 메뉴에서 S 를 검색하고 선택한 뒤 스케일(Scale) 값을 -1.0 으로 설정합니다.
-
축 매핑(Axis Mappings) 옆의 + 기호를 클릭하여 새 축 입력을 생성합니다. 새 입력을 MoveRight 로 명명합니다.
-
MoveRight 축 매핑 옆의 + 기호를 클릭하여 키를 추가하고, 아래 이미지와 같이 MoveRight 키 매핑을 D 와 S , 스케일을 각각 1.0 과 -1.0 으로 구성합니다.
-
바인딩(Bindings) 카테고리에서 축 매핑(Axis Mappings) 옆의 + 기호를 클릭하여 Turn 이라는 이름의 새 입력을 생성합니다. 입력 매핑 키로 마우스 X(Mouse X) 를 검색하고 선택합니다.
-
바인딩(Bindings) 카테고리에서 축 매핑(Axis Mappings) 옆의 + 기호를 클릭하여 LookUp 이라는 이름의 새 입력을 생성합니다. 입력 매핑 키로 마우스 Y(Mouse Y) 를 검색하고 선택한 뒤 스케일(Scale) 값을 -1.0 으로 설정합니다.
-
BP_CameraCharacter 를 더블클릭하고 이벤트 그래프(Event Graph) 로 이동한 다음, 그래프를 우클릭하여 축 이벤트(Axis Event) 인 MoveForward 를 검색하고 선택합니다.
이미지를 클릭하면 확대됩니다.
-
MoveForward 입력 축 노드의 실행 핀에서 드래그하여 드롭다운 메뉴 에서 Add Movement Input 노드를 검색하고 선택한 다음, MoveForward 입력 축 노드의 Axis Value 핀을 Add Movement Input 노드의 Scale Value 핀에 연결합니다.
이미지를 클릭하면 확대됩니다.
-
이벤트 그래프(Event Graph) 를 우클릭하고 컨텍스트 메뉴(context menu) 에서 Get Control Rotation 을 검색하고 선택합니다. Return Value 핀에서 드래그하여 드롭다운 메뉴 에서 Break Rotator 를 검색하고 선택합니다.
이미지를 클릭하면 확대됩니다.
-
Break Rotator 노드의 Z(Yaw) 핀에서 드래그하여 드롭다운 메뉴에서 Make Rotator 를 검색하고 선택합니다. Make Rotator 노드의 Return Value 핀에서 드래그하여 드롭다운 메뉴에서 Get Forward Vector 를 검색하고 선택합니다.
이미지를 클릭하면 확대됩니다.
-
Get Forward Vector 노드의 Return Value 핀에서 드래그하여 Add Movement Input 노드의 World Direction 핀에 연결합니다.
이미지를 클릭하면 확대됩니다.
-
이벤트 그래프(Event Graph) 를 다시 우클릭하여 축 이벤트(Axis Event) 인 MoveRight 를 검색하고 선택합니다.
이미지를 클릭하면 확대됩니다.
-
MoveRight 입력 축 노드의 실행 핀에서 드래그하여 드롭다운 메뉴 에서 Add Movement Input 노드를 검색하고 선택합니다. MoveRight 입력 축 노드의 Axis Value 핀을 Add Movement Input 노드의 Scale Value 핀에 연결합니다.
이미지를 클릭하면 확대됩니다.
-
Make Rotator 노드의 Return Value 핀에서 드래그하여 드롭다운 메뉴 에서 Get Right Vector 노드를 검색하고 선택합니다. Get Right Vector 노드의 Return Value 핀에서 드래그하여 Add Movement Input 노드의 World Direction 핀에 연결합니다.
이미지를 클릭하면 확대됩니다.
완성된 이동 입력 이벤트(Movement Input Events) 는 아래 이미지와 같은 모습입니다.
이미지를 클릭하면 확대됩니다.
-
이벤트 그래프(Event Graph) 를 우클릭하여 LookUp 축 이벤트 노드를 검색하고 선택합니다. 이벤트 그래프를 다시 우클릭하여 Add Controller Pitch Input 노드를 검색하고 선택합니다.
-
LookUp 입력 축 노드의 Axis Value 핀에서 드래그하여 Add Controller Pitch Input 노드의 Val 핀에 연결합니다. LookUp 입력 축 노드의 실행 출력 핀에서 드래그하여 Add Controller Pitch Input 노드의 실행 입력 핀에 연결합니다.
이미지를 클릭하면 확대됩니다.
-
이벤트 그래프(Event Graph) 를 우클릭하여 Turn 입력 축 이벤트 노드를 검색하고 선택합니다. 이벤트 그래프를 다시 우클릭하여 Add Controller Yaw Input 노드를 검색하고 선택합니다.
-
Turn 입력 축 노드의 Axis Value 핀에서 드래그하여 Add Controller Yaw Input 노드의 Val 핀에 연결합니다. Turn 입력 축 노드의 실행 출력 핀에서 드래그하여 Add Controller Yaw Input 노드의 실행 입력 핀에 연결합니다.
이미지를 클릭하면 확대됩니다.
-
컴파일(Compile) 과 저장(Save) 을 클릭합니다.
새로 구현한 스프링 암 컴포넌트의 기능을 시연하려면 캐릭터 클래스에 이동 입력을 추가해야 합니다.
-
우선 편집(Edit) > 프로젝트 세팅(Project Settings) > 엔진(Engine) > 입력(Input) 으로 이동한 다음, 바인딩(Bindings) 카테고리에서 축 매핑(Axis Mappings) 옆의 + 기호를 클릭하여 새 축 매핑을 생성합니다.
-
새 축 매핑을 MoveForward 로 명명한 다음 드롭다운 키 매핑 메뉴에서 W 를 검색하고 선택합니다.
-
MoveForward 축 매핑 옆의 + 기호를 클릭하여 키를 추가합니다. 드롭다운 메뉴에서 S 를 검색하고 선택한 뒤 스케일(Scale) 값을 -1.0 으로 설정합니다.
-
축 매핑(Axis Mappings) 옆의 + 기호를 클릭하여 새 축 입력을 생성합니다. 새 입력을 MoveRight 로 명명합니다.
-
MoveRight 축 매핑 옆의 + 기호를 클릭하여 키를 추가하고, 아래 이미지와 같이 MoveRight 키 매핑을 D 와 S , 스케일을 각각 1.0 과 -1.0 으로 구성합니다.
-
바인딩(Bindings) 카테고리에서 축 매핑(Axis Mappings) 옆의 + 기호를 클릭하여 Turn 이라는 이름의 새 입력을 생성합니다. 입력 매핑 키로 마우스 X(Mouse X) 를 검색하고 선택합니다.
-
바인딩(Bindings) 카테고리에서 축 매핑(Axis Mappings) 옆의 + 기호를 클릭하여 LookUp 이라는 이름의 새 입력을 생성합니다. 입력 매핑 키로 마우스 Y(Mouse Y) 를 검색하고 선택한 뒤 스케일(Scale) 값을 -1.0 으로 설정합니다.
-
CameraCharacter.cpp에서 ACameraCharacter::MoveForward 및 ACameraCharacter::MoveRight 클래스 메서드에 적용될 아래의 로직을 구현합니다.void ACameraCharacter::MoveForward(float AxisValue) { if ((Controller != nullptr) && (AxisValue != 0.0f)) { // 앞쪽 찾기 const FRotator Rotation = Controller->GetControlRotation(); const FRotator YawRotation(0, Rotation.Yaw, 0); // 앞쪽 벡터 구하기 const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X); AddMovementInput(Direction, AxisValue); } } void ACameraCharacter::MoveRight(float AxisValue) { if ((Controller != nullptr) && (AxisValue != 0.0f)) { // 오른쪽 찾기 const FRotator Rotation = Controller->GetControlRotation(); const FRotator YawRotation(0, Rotation.Yaw, 0); // 오른쪽 벡터 구하기 const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y); // 해당 방향으로 이동 추가 AddMovementInput(Direction, AxisValue); } } -
그런 다음 ACameraCharacter::SetupPlayerInputComponent 메서드로 이동하여 아래의 코드를 구현합니다.
//함수 기능을 입력에 바인딩하기 위해 호출 void ACameraCharacter::SetupPlayerInputComponent(UInputComponent*) { Super::SetupPlayerInputComponent(PlayerInputComponent); PlayerInputComponent->BindAxis("MoveForward",this, &ACameraCharacter::MoveForward); PlayerInputComponent->BindAxis("MoveRight", this, &ACameraCharacter::MoveRight); PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput); PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput); }
캐릭터(Character) 클래스는 폰(Pawn) 클래스로부터 상속받습니다. 이 예시에서는 폰의 AddControllerPitchInput 및 AddControllerYawInput 클래스 메서드를 사용하여 Turn과 LookUp 로직을 처리했습니다.
레벨 구성
스프링 암 컴포넌트 기능을 시연하려면 레벨에 지오메트리 방해물을 배치해야 합니다.
-
에디터에서 창(Window) > 액터 배치(Place Actors) 를 클릭하고 액터 배치 패널을 엽니다.
-
액터 배치 패널에서 지오메트리(Geometry) 탭을 열고 레벨에 박스 브러시(Box Brush) 를 추가합니다.
Click image to enlarge
-
디테일 패널에서 브러시 세팅 카테고리를 찾아 X, Y, Z 값을 조정하여 박스 브러시의 경계를 조정할 수 있습니다.
Click image to enlarge
-
다음으로 툴바에서 PIE(Play In Editor) 를 클릭합니다.
최종 결과

캐릭터를 이동할 때 WASD를 사용하면 카메라가 이제 캐릭터의 움직임에 약간 뒤처지는 것을 알 수 있습니다. 또한 캐릭터가 벽 근처를 이동할 때 카메라는 자신을 다시 배치하려고 시도하고 가까이 이동합니다. 캐릭터가 장애물 없이 자유롭게 움직일 때 Spring Arm은 기본 클래스 프로퍼티에서 지정된 타깃 암 길이(Target Arm Length) 로 카메라를 되돌립니다.