UE5 Issues : ADS (Aim Offset 1D)

2025. 3. 5. 23:50·Unreal Engine

1. 3인칭 시점


기본적으로 카메라는 spring arm과 함께 존재하는 것이 조절하기 편리하다.

특히 각도와 위치 관련된 부분에 있어서 조절할 때 spring arm 의 offset을 조절하는 것이 더 좋은 방식이다.

 

우선 아래와 같이 구성을 하게 되었다.

  • 상위 컴포넌트는 spring arm 이고 하위 컴포넌트를 child actor로 하였다.
  • child actor로 두면 나중에 GetChildActor를 통해서 가져올 때 편리하기 때문이다.

  • Child Actor에는 Camera를 상속해서 만든 클래스를넣어주면 된다.

코드는 아래와 같이 구성하였다.

  • 헤더파일
//change view component
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component")
TObjectPtr<USpringArmComponent> TPSSpringArmComp;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Component")
TObjectPtr<UChildActorComponent> TPSCamera;
  • 생성자
    • SetChildActorClass에서 StaticClass를 쓰는 부분은 해당 글을 참고하면 된다.
    • 추가적으로 pitch 회전을 위해서 bUsePawnControlRotation을 true로 세팅해줘야 한다.
TPSSpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("TPS Spring Arm"));
TPSSpringArmComp->SetupAttachment(RootComponent);
TPSCamera = CreateDefaultSubobject<UChildActorComponent>(TEXT("TPS Camera actor"));
TPSCamera->SetupAttachment(TPSSpringArmComp);
TPSCamera->SetChildActorClass(APlayerCamera::StaticClass());

TPSSpringArmComp->TargetArmLength = 200.f;
TPSSpringArmComp->TargetOffset = FVector(0.f, 0.f, 100.f);
TPSSpringArmComp->bUsePawnControlRotation = true;

 

 

2. 줌인 카메라 (ADS)


정말 여러가지 방법을 사용해 보았는데, 내가 원하는 시점을 딱 맞추는 방법으로는 무기에 카메라를 두는 것이 가장 좋은 방식이라는 생각이 들었다.

 

이때 주의할 점 몇가지가 존재한다.

 

주의점 1) 카메라의 위치를 조절할 때는 spring arm의 socket offset을 조절하기

  • 직접 카메라의 location이나 rotation을 바꾸거나 
  • target offset을 바꾸는 방식은 원하는 결과가 나오지 않을때가 많았다. 
  • 아마도 에셋마다 기존의 각도가 다르기 (축이 다른 경우가 존재) 때문이라는 생각이 들었다.

주의점 2) 애니메이션에서 aim offset을 사용할 때 get base aim rotation을 사용하지 말고, get control rotation을 사용하기

  • 아직 이유는 정확하게 파악하지는 못하였지만,
    • get base aim rotation 노드를 사용할 때 무기의 카메라로 시점이 변경되면,
    • pitch 값이 고정되면서 pitch 회전이 되지 않는 문제가 있었다.
    • 그러나 control rotation 값은 제대로 출력되는 것을 보고 해당 함수를 수정해 보았더니 제대로 동작하게 되었다.

오른쪽 노드 쓰기

 

구현 방법

 

1. 3인칭 카메라와 스프링암은 위에서 처럼 세팅을 하면 된다.

 

2. 무기 카메라와 스프링암도 캐릭터와 마찬가지로 세팅을 하면 된다.

  • 헤더
//for zoom in
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Component")
TObjectPtr<USpringArmComponent> WeaponSpringArmComp;

UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Component")
TObjectPtr<UChildActorComponent> WeaponCameraComp;
  • 생성자
    • 이때 TargetArmLength는 0으로 해줘야 하고
    • Rotation을 확인한 후 에셋과 일직선이 되도록 돌려서 기본 값 세팅을 해주었다.

WeaponSpringArmComp = CreateDefaultSubobject<USpringArmComponent>(TEXT("Spring Arm"));
WeaponSpringArmComp->SetupAttachment(RootComponent);
WeaponSpringArmComp->TargetArmLength = 0.f;
WeaponSpringArmComp->SetRelativeLocation(FVector(0.f, 0.f, 0.f));
WeaponSpringArmComp->SetRelativeRotation(FRotator(0.f, 90.f, 0.f));
WeaponSpringArmComp->bUsePawnControlRotation = true;

WeaponCameraComp = CreateDefaultSubobject<UChildActorComponent>(TEXT("Weapon Camera"));
WeaponCameraComp->SetupAttachment(WeaponSpringArmComp);
WeaponCameraComp->SetChildActorClass(APlayerCamera::StaticClass());
WeaponCameraComp->SetRelativeLocation(FVector(0.f, 0.f, 0.f));
WeaponCameraComp->SetRelativeRotation(FRotator(0.f, 0.f, 0.f));

3. 추가적으로 각 무기마다 위치를 보면서 스프링암의 위치를 조절해주면 된다.

WeaponSpringArmComp->SocketOffset = FVector(-8.f, 0.f, 20.f);

4. 우리가 줌인을 하는 순간 SetViewTargetWithBlend 함수를 사용하면 된다.

void APlayerCharacter::ZoomInOut(const FInputActionValue& value)
{	
	if (bIsWeaponEquipped && !bIsRolling)
	{
		if (GetController())
		{
			APlayerCharacterController* PlayerCharacterController = Cast<APlayerCharacterController>(GetController());

			if (PlayerCharacterController)
			{
				if (bIsTPSMode)
				{
					if (CurrentWeapon)
					{
						PlayerCharacterController->SetViewTargetWithBlend(CurrentWeapon->WeaponCameraComp->GetChildActor(), 0.2f);									
					}					
					bIsTPSMode = false;
				}
				else
				{
					PlayerCharacterController->SetViewTargetWithBlend(TPSCamera->GetChildActor(), 0.2f);

					bIsTPSMode = true;
				}
			}
		} 
	}
}

 

5. 애니메이션 세팅은 아래와 같이 해주면 된다.

  • 이벤트 그래프에서 pitch 라는 변수를 만들어 준다.

  • 애님 그래프는 아래와 같이 구성해야 한다.

  • iron sight state 는 아래와 같이 에임 오프셋을 사용하면 된다.
    • 여기서 pitch는 위의 이벤트 그래프에서 만든 값을 넣고
    • base pose는 additve가 아닌! pose를 넣어주면 된다.

iron sight state 내부 모습

 

추가) 에임 오프셋 구현

  • 애니메이션 -> 레거시 -> 에임오프셋 1D를 생성
  • axis setting 에서 pitch 값을 -90 ~ 90으로 지정해준다.
  • 애니메이션을 아래 그래프에 넣어주면 된다. 이때 주의할 점은 애니메이션을 additive 로 만들어야 한다는 점이다!

  • 애니메이션 additive 로 만들기
    • 애니메이션 시퀀스를 열고 아래 사진처럼 세팅을 해주면 된다.
    • 애디티브 타입을 mesh space
    • 베이스 포즈 타입을 selected animation scaled로 지정
    • 이때 베이스 애니메이션은 에임 오프셋에서 center로 (pitch가 0일때) 사용할 애니메이션을 넣으면 된다.

 

결과 모습

 

 

'Unreal Engine' 카테고리의 다른 글

Unreal Engine - 채팅 (리슨 서버)  (0) 2025.03.14
Unreal Engine - Main Menu (흐름 위주의 정리)  (0) 2025.03.07
Unreal Engine - Sound play & Effect spawn  (0) 2025.03.05
Unreal Engine - 애님 몽타주  (0) 2025.03.05
Unreal Engine - 캐릭터 앉기 및 구르기  (0) 2025.03.05
'Unreal Engine' 카테고리의 다른 글
  • Unreal Engine - 채팅 (리슨 서버)
  • Unreal Engine - Main Menu (흐름 위주의 정리)
  • Unreal Engine - Sound play & Effect spawn
  • Unreal Engine - 애님 몽타주
gbleem
gbleem
gbleem 님의 블로그 입니다.
  • gbleem
    gbleem 님의 블로그
    gbleem
  • 전체
    오늘
    어제
    • 분류 전체보기 (184)
      • Unreal Engine (73)
      • C++ (19)
      • 알고리즘(코딩테스트) (27)
      • TIL (60)
      • CS (4)
      • 툴 (1)
  • 블로그 메뉴

    • 홈
    • 카테고리
  • 링크

    • 과제용 깃허브
    • 깃허브
    • velog
  • 공지사항

  • 인기 글

  • 태그

    매크로 지정자
    additive animation
    character animation
    applydamage
    싱글턴
    상속
    C++
    motion matching
    DP
    Vector
    const
    gamestate
    cin함수
    템플릿
    blend pose
    enhanced input system
    addonscreendebugmessage
    map을 vector로 복사
    actor 클래스
    BFS
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
gbleem
UE5 Issues : ADS (Aim Offset 1D)
상단으로

티스토리툴바