Youngki Jeong | Game Dev Lab
HomeProjectsEvidenceJourneyAbout
SearchGitHub글쓰기

Youngki Jeong | Game Dev Lab

Unreal C++ 게임개발 포트폴리오 & 개발 기록

Projects·Evidence·Journey·About·GitHub Portfolio·GitHub

빠른 검색

프로젝트, Evidence, 디버깅 노트, 학습 기록을 검색합니다.

← 목록으로
← 목록으로
IT-B02

Input과 GAS State가 ADS Camera로 이어지는 구조

2026년 9월 7일
·
JEONGYOUNGKI
Description

InputTag.ADS → Ability → CameraMode.ADS → Camera Policy → CameraModeStack → Player View로 이어지는 Integration Boundary를 정리한 글입니다.

Project

ImitationTrigger

ArticleType

Runtime Flow

SourceBoundary

My Integration

EvidenceLevel

Asset

Priority

S

Tags

GAS

ProofType

Asset

Audience

Technical Interviewer

CareerTrack

Gameplay

목차

ImitationTrigger — Input과 GAS State가 ADS Camera로 이어지는 구조

RMB를 눌렀다고 Camera가 바로 바뀌는 것은 아닙니다

플레이어 입장에서 ADS는 단순합니다.

Text
RMB Hold
→ ADS
 
RMB Release
→ ThirdPerson

하지만 Source를 따라가 보면 Camera가 바뀌기 전까지 몇 개의 서로 다른 상태를 거칩니다.

Text
RMB
→ IA_Character_SecondaryAction
→ InputTag.ADS
→ GA_DefaultADS AbilitySpec
→ Ability Activation
→ CameraMode.ADS
→ PawnData.CameraModeRules
→ CM_ThirdPerson_ADS
→ CameraModeStack
→ Player View

처음에는 이름에 ADS가 붙어 있어 같은 상태처럼 보였습니다. 하지만 실제로는 역할이 다릅니다.

Text
InputTag.ADS
= 입력의 Gameplay 의미
 
GA_DefaultADS Active
= GAS Ability Runtime State
 
CameraMode.ADS
= 다른 System에 노출되는 Gameplay State
 
CM_ThirdPerson_ADS
= 그 State에서 사용할 Camera View Policy

이 차이를 이해한 것이 ADS Flow를 정리할 때 가장 중요했습니다.


Input은 Ability를 찾기 위한 의미로 바뀝니다

시작은 물리적인 RMB입니다.

Text
RightMouseButton
→ IA_Character_SecondaryAction

그다음 InputConfig에서 InputAction에 Gameplay 의미를 연결합니다.

Text
IA_Character_SecondaryAction
→ InputTag.ADS

여기서:

Text
InputAction
!=
InputTag

입니다.

InputAction은 Enhanced Input 쪽 입력이고, InputTag.ADS는 Gameplay 쪽에서 사용하는 의미입니다.

Ability 입력이 들어오면 ASC는 자신이 가진 AbilitySpec 중 InputTag.ADS와 연결된 Spec을 찾습니다.

Text
InputTag.ADS
→ Matching AbilitySpec
→ Input Queue

이 시점에서도 Ability가 이미 실행된 것은 아닙니다.

Text
InputTag가 들어왔다
!=
Ability가 Active다

입력 Queue가 처리되고 Activation이 성공해야 GA_DefaultADS가 실제 Runtime State가 됩니다.


Ability는 입력 전에 준비되어 있어야 합니다

Runtime에서 InputTag.ADS로 Ability를 찾으려면 그보다 먼저 GA_DefaultADS의 AbilitySpec이 ASC에 Grant되어 있어야 합니다.

프로젝트에서는 팀의 AbilitySet 구조가 이 준비를 담당합니다.

Text
PawnData
→ AbilitySets
→ AbilitySpec
→ ASC GiveAbility

ADS 기준으로는 Ability Class와 InputTag.ADS 연결이 함께 준비되어 있어야 합니다.

Text
GA_DefaultADS
+
InputTag.ADS
→ AbilitySpec
→ ASC

그래서:

Text
GA_DefaultADS Class가 존재한다
!=
RMB 입력으로 그 Ability를 찾을 수 있다

입니다.

이 AbilitySet / ASC Input Pipeline 자체는 제가 만든 구조가 아니라 팀 Gameplay Framework입니다. 제가 이 흐름을 깊게 본 이유는 제 Camera 기능보다 앞에서 어떤 Runtime State가 준비되는지 알아야 했기 때문입니다.


Ability State와 Camera State 사이에 GameplayTag를 두었습니다

GA_DefaultADS가 Active되면 Camera가 바로 조작되는 것이 아니라 CameraMode.ADS라는 Gameplay State가 노출됩니다.

Text
GA_DefaultADS Active
→ CameraMode.ADS

여기서도:

Text
CameraMode.ADS
!=
CM_ThirdPerson_ADS

입니다.

CameraMode.ADS는 GameplayTag State이고, CM_ThirdPerson_ADS는 실제 View를 만드는 CameraMode입니다.

둘 사이의 연결은 PawnData.CameraModeRules에 있습니다.

Text
CameraMode.ADS
→ CameraModeRules
→ CM_ThirdPerson_ADS

이렇게 State와 View Policy 사이에 한 단계가 있기 때문에 Ability가 CameraComponent를 직접 찾아가 FOV나 위치를 수정할 필요가 없습니다.

Text
Gameplay
= 현재 ADS 상태다.
 
Camera Policy
= 이 상태에서는 ADS CameraMode를 사용한다.
 
Camera Runtime
= 선택된 Mode를 실제 View로 만든다.

PawnData는 State Owner가 아니라 Configuration Hub입니다

ADS를 따라가면서 PawnData의 역할도 다시 구분했습니다.

한 Pawn에서 필요한 설정은 다음처럼 묶여 있습니다.

Text
PawnData
 
├─ InputConfig
├─ AbilitySets
├─ DefaultCameraMode
└─ CameraModeRules

ADS 기준으로 보면:

Text
InputConfig
→ InputAction과 InputTag 연결
 
AbilitySets
→ GA_DefaultADS 준비
 
DefaultCameraMode
→ CM_ThirdPerson
 
CameraModeRules
→ CameraMode.ADS
   → CM_ThirdPerson_ADS

중요한 점은 PawnData가 ADS 상태를 직접 실행하는 객체가 아니라는 것입니다.

Text
PawnData
= Configuration
 
ASC
= Ability / GameplayTag Runtime State
 
CameraModeStack
= 선택된 CameraMode Runtime 실행

따라서:

Text
Asset Wired
!=
Runtime State Active

입니다.

DataAsset에 CameraMode.ADS → CM_ThirdPerson_ADS Rule이 있다는 사실만으로 현재 플레이어가 ADS 상태라는 뜻은 아닙니다.


PlayerState와 Character도 같은 책임을 가지지 않습니다

ADS Runtime State를 따라갈 때 ASC의 Owner도 구분해야 했습니다.

ImitationTrigger에서는:

Text
ASC OwnerActor
= AITPlayerState
 
ASC AvatarActor
= AITCharacter

로 연결됩니다.

그래서 큰 역할을 나누면:

Text
PlayerState ASC
= AbilitySpec / Ability / GameplayTag State
 
AITCharacter
= 실제 World Pawn
 
UITCameraComponent
= Player Camera Runtime

입니다.

Character가 ASC를 조회할 수 있다고 해서 Character가 Ability State의 Owner인 것은 아닙니다.

AITCharacter는 모든 기능을 직접 수행하는 거대한 Class라기보다 여러 시스템이 같은 Pawn을 기준으로 만나는 Assembly Root에 가깝습니다.

Text
AITCharacter
├─ HeroComponent
├─ CameraComponent
├─ PawnData
└─ PlayerState ASC와 Avatar 관계

제가 Character 쪽에서 직접 설명하는 범위도 전체 Character Framework가 아니라, 이 조립 지점에 UITCameraComponent를 연결해 제가 구현한 CameraModeStack의 결과가 실제 Player View로 이어지도록 한 부분입니다.


ADS State가 만들어진 뒤부터 Camera Runtime으로 넘어옵니다

현재 CameraMode.ADS가 존재하면 Camera Policy에서 해당 Rule을 찾습니다.

Text
ASC Owned Tags
→ CameraMode.ADS
 
        ↓
 
PawnData.CameraModeRules
→ Match
 
        ↓
 
CM_ThirdPerson_ADS

ADS State가 없거나 맞는 Rule이 없다면 기본 CameraMode를 사용합니다.

Text
No ADS State
→ DefaultCameraMode
→ CM_ThirdPerson

선택된 CameraMode Class가 결정되면 그때부터 Camera Runtime의 책임입니다.

Text
CM_ThirdPerson_ADS
→ UITCameraComponent
→ CameraModeStack
→ ADS View

그래서 제가 ImitationTrigger에서 가장 중심으로 설명하는 Integration Boundary는 다음입니다.

Text
Team Input / GAS / PawnData
 
        ↓
 
CameraMode.ADS
→ CameraModeRules
→ CM_ThirdPerson_ADS
 
        ↓
 
My Camera Runtime
→ CameraModeStack
→ Player View

Release도 같은 흐름을 반대로 따라갑니다

ADS는 들어가는 것뿐 아니라 나오는 흐름도 중요합니다.

RMB를 놓고 ADS Ability가 종료되면 활성 중이던 CameraMode.ADS State도 사라집니다.

Text
RMB Release
→ ADS Ability End
→ CameraMode.ADS OFF
→ Camera Policy 재평가
→ DefaultCameraMode
→ CM_ThirdPerson
→ CameraModeStack
→ TPS View

즉 Release를 단순히:

Text
FOV를 원래 값으로 돌린다

라고 보기보다:

Text
Input Lifetime End
→ Ability Lifetime End
→ Gameplay State 제거
→ Camera Policy 재평가
→ Default View 복귀

로 보는 편이 구조를 더 정확하게 설명합니다.


팀 Framework와 제 기여 범위

이 전체 Flow의 모든 코드를 제가 만든 것은 아닙니다.

Text
Team Gameplay Framework
- InputConfig / InputComponent
- AbilitySet
- AbilitySystemComponent
- PlayerState ASC
- PawnData
- HeroComponent Base
- UITADSAbility C++ Base

제가 직접 구현으로 설명하는 Camera 영역은:

Text
AITPlayerCameraManager
UITCameraComponent
UITCameraMode
UITCameraModeStack
UITCameraMode_ThirdPerson

그리고 제가 가장 중심으로 가져가는 Integration은:

Text
CameraMode.ADS
→ CameraModeRules
→ CM_ThirdPerson_ADS
→ CameraModeStack

입니다.

팀 Framework가 만든 Gameplay State를 읽고, 그 결과가 제가 구현한 Camera Runtime으로 넘어오도록 연결한 부분입니다.


현재 검증 범위

현재 Source와 Static Asset Wiring 기준으로 다음 흐름은 추적되어 있습니다.

Text
InputTag.ADS
→ GA_DefaultADS
 
GA_DefaultADS
→ CameraMode.ADS
 
CameraMode.ADS
→ CM_ThirdPerson_ADS
 
CM_ThirdPerson_ADS
→ CameraModeStack

하지만:

Text
Source / Asset Wiring
!=
최신 End-to-End Runtime Verified

입니다.

최신 PIE에서 Press → Hold → Release와 Player-visible TPS → ADS → TPS 결과까지 한 번에 닫는 것은 별도 Runtime Verification 범위로 남겨두고 있습니다.


정리

ImitationTrigger의 ADS를 따라가면서 가장 크게 남은 것은 입력과 화면 사이에 하나의 ADS 상태만 존재하는 것이 아니라는 점이었습니다.

Text
Physical Input
→ Gameplay Input Meaning
→ Ability Runtime
→ Gameplay State
→ Camera Policy
→ CameraMode
→ Camera Runtime
→ Player View

그리고 각 단계의 Owner도 달랐습니다.

Text
PawnData
= Configuration
 
PlayerState ASC
= Gameplay Runtime State
 
Character
= World Pawn / Assembly Root
 
CameraComponent
= Camera Runtime

플레이어에게는 RMB → ADS라는 한 장면으로 보이지만, 내부에서는 여러 시스템의 책임이 순서대로 연결됩니다.

제가 이 프로젝트에서 가져간 경험은 팀 GAS Framework 전체를 구현한 것이 아니라, 그 Framework가 만든 State가 제 Camera 기능으로 넘어오는 경계를 읽고 실제 Player View까지 연결한 경험이었습니다.

다음 글에서는 Camera와 ADS Flow에서 잠시 벗어나, 멀티플레이 Runtime에서 Server / Client / Role 실행 문맥을 빠르게 확인하기 위해 만든 ITLogChannel과 Network Debug Utility를 정리합니다.

빠른 검색

프로젝트, Evidence, 디버깅 노트, 학습 기록을 검색합니다.

목차