Animator
3D 모델 애니메이션 시스템은 다음과 같은 핵심 원리를 기반으로 합니다:
효율적인 데이터 구조: 메시, 뼈, 머티리얼, 애니메이션 데이터를 효율적으로 관리하는 구조
계층적 뼈 구조: 부모-자식 관계로 연결된 뼈 계층 구조를 통한 자연스러운 움직임 표현
좌표계 변환 처리: T-포즈 기준의 루트 변환을 로컬 변환으로 변환하고 적용하는 명확한 처리 과정
GPU 최적화: 애니메이션 데이터를 GPU 친화적인 텍스처 형태로 변환하여 효율적인 처리 가능
블렌딩 지원: 두 애니메이션 간 부드러운 전환을 위한 블렌딩 구현
전체 데이터 흐름도
메시와 뼈 데이터 로드 과정
데이터 로드 흐름도
핵심 코드 분석
BindCacheInfo() 함수는 모델의 여러 구성 요소 간의 관계를 설정하는 중요한 역할을 합니다:
메시와 머티리얼 연결
메시와 뼈 연결
뼈 계층 구조 구성 (부모-자식 관계)
Material 데이터 로드 과정
데이터 로드 흐름도
Material 로드 핵심 요소
XML 파일에서 다음 정보를 로드합니다:
Material 이름: 고유 식별자
텍스처 경로: 디퓨즈, 스페큘러, 노말 맵
머티리얼 속성: 앰비언트, 디퓨즈, 스페큘러, 이미시브 색상
애니메이션 데이터 로드 및 텍스처 변환 과정
애니메이션 처리 흐름도
주요 코드 분석 및 접근 방식
이 코드는 애니메이션의 기본 정보와 각 뼈마다의 키프레임 데이터를 로드합니다.
애니메이션 변환 행렬 계산 (CreateAnimationTransform)
이 부분은 Root 기준 Transform을 뼈 계층 구조에 맞게 변환하는 핵심 과정입니다:
애니메이션 변환 과정 시각화
핵심 이해 포인트:
T-포즈에서 뼈 변환: 각 뼈는 T-포즈에서의 글로벌 변환 행렬(bone->transform)을 가집니다.
로컬 좌표계로 변환: 이 글로벌 변환의 역행렬(invGlobal)을 사용하여 로컬 좌표계로 변환합니다.
애니메이션 변환 적용: 키프레임 데이터(스케일, 회전, 이동)를 사용하여 애니메이션 변환 행렬을 계산합니다.
부모 영향 적용: 부모 뼈의 변환을 적용하여 계층 구조를 유지합니다.
최종 변환 계산: invGlobal * tempAnimBoneTransforms[b]를 통해 최종 변환 행렬을 계산합니다.
invGlobal: T-포즈 글로벌 → 로컬 변환
tempAnimBoneTransforms[b]: 애니메이션 적용 후 글로벌 변환
애니메이션 데이터를 텍스처로 변환 (CreateTexture)
텍스처의 메모리 레이아웃 시각화
셰이더에서의 활용
Animator의 개념
Animator는 3D 모델의 다양한 애니메이션 클립들과 그 사이의 전환(트랜지션)을 관리하는 시스템입니다. 이는 게임 캐릭터나 객체의 여러 동작 상태(달리기, 점프, 공격 등)를 자연스럽게 연결하고 제어할 수 있게 해줍니다.
Animator 컴포넌트는 다음 주요 기능을 제공합니다:
애니메이션 클립 관리: 여러 애니메이션 클립을 등록하고 관리
트랜지션 시스템: 클립 간 자연스러운 전환을 위한 트랜지션 정의
파라미터 기반 제어: 불리언, 정수, 부동소수점 파라미터를 통한 상태 전환 조건 설정
기본 클립 설정: 시작 시 자동으로 재생될 기본 클립 지정
Animator에서 사용하는 구조들
Clip 구조체
name: 클립의 고유 이름
isLoop: 반복 재생 여부
animIndex: 모델의 애니메이션 배열에서의 인덱스
progressRatio: 현재 재생 진행률(0~1)
transitions: 이 클립에서 다른 클립으로의 전환 정보
Transition 구조체
clipA / clipB: 시작 클립과 목표 클립
flag: 트랜지션 활성화 여부
hasExitTime: exitTime에 도달해야만 전환이 시작되는지 여부
exitTime: 소스 클립의 얼마만큼 진행 후 전환을 시작할지(0~1)
transitionDuration: 전환에 걸리는 시간(초)
conditions: 이 트랜지션이 발생하기 위한 조건들의 배열
Parameter와 Condition 구조체
이 구조들은 애니메이션 전환 조건을 정의합니다:
Parameter: 애니메이터의 상태를 나타내는 변수(불리언, 정수, 부동소수점)
Condition: 파라미터가 특정 값과 특정 관계인지 검사하는 조건(같음, 다름, 큼, 작음)
애니메이션 블렌딩 구조체
이 구조체들은 두 애니메이션 사이의 블렌딩(혼합) 정보를 처리합니다:
KeyframeDesc: 현재 프레임, 다음 프레임, 두 프레임 사이의 혼합 비율 등을 포함
blendFrameDesc: 두 애니메이션 클립 사이의 블렌딩 정보를 포함
GUIManager에서 애니메이터 에디팅
GUIManager는 애니메이터 그래프를 시각적으로 편집할 수 있는 인터페이스를 제공합니다. 핵심 기능은 다음과 같습니다:
트랜지션 설정
클립 사이의 연결 그리기
Animator의 동작 원리와 셰이더 연동
Animator::Update 함수
이 함수는 다음을 수행합니다:
트랜지션 중이면 블렌딩 처리
아니면 현재 클립을 재생하고 진행률 업데이트
조건을 체크하여 트랜지션 플래그 설정
애니메이션 이벤트가 있으면 처리
진행 중인 트랜지션이 있으면 해당 트랜지션으로 전환
트랜지션 블렌딩 처리
이 함수는 두 애니메이션 클립 간의 블렌딩을 처리합니다:
두 클립의 현재 상태(프레임, 진행률 등) 계산
블렌딩 비율 계산(시간 기반)
블렌딩 정보를 셰이더에 전달하기 위한 구조체 설정
블렌딩이 완료되면 목표 클립으로 완전히 전환
조건 확인 및 트랜지션 플래그 설정
이 함수는 모든 트랜지션에 대해:
각 조건을 파라미터 값과 비교하여 검사
exitTime 조건이 있으면 현재 클립의 진행률이 충분한지 체크
모든 조건이 만족되면 트랜지션 플래그를 활성화
셰이더에서의 애니메이션 블렌딩 처리
이 셰이더 함수는:
각 정점에 영향을 주는 뼈 인덱스와 가중치를 가져옴
현재 애니메이션과 전환 중인 애니메이션(있는 경우)의 프레임 정보를 로드
TransformMap 텍스처에서 각 뼈의 변환 행렬을 가져옴
프레임 사이의 보간을 통해 부드러운 애니메이션 제공
두 애니메이션 사이의 블렌딩(필요한 경우)
각 뼈의 가중치를 적용하여 최종 변환 행렬 계산
애니메이터 시스템 시각화
애니메이션 이벤트
애니메이션 이벤트 실행 흐름
등록 단계:
REGISTER_MONOBEHAVIOR_METHOD 매크로를 통해 함수 등록
클래스 이름과 함수 이름으로 구성된 키로 MethodRegistry에 저장
이벤트 설정 단계:
GUIManager를 통해 애니메이션 타임라인에 이벤트 추가
애니메이션 클립의 특정 시간(0-1 사이의 진행률)에 이벤트 연결
게임오브젝트의 MonoBehaviour에서 사용 가능한 함수 목록에서 선택
런타임 실행 단계:
Animator::Update에서 애니메이션 진행률 추적
진행률이 이벤트 시간에 도달하면 InvokeAnimationEvent 호출
MethodRegistry에서 함수 포인터를 가져와 실행
이벤트 플래그를 설정하여 중복 호출 방지
리셋 단계:
애니메이션 루프가 완료되면 모든 이벤트 플래그 리셋
다음 루프에서 이벤트가 다시 발생할 수 있도록 함
이벤트 관련 구조체
time: 애니메이션 진행률(0~1 사이)에 해당하는 이벤트 발생 시간
function: 호출할 함수 정보(스크립트 객체와 함수 키)
isFuctionCalled: 이벤트가 이미 호출되었는지 추적하는 플래그
MethodRegistry 시스템
MethodRegistry는 함수 참조를 문자열 키로 관리하는 전역 레지스트리입니다. 이것은 런타임에 함수를 동적으로 찾고 호출할 수 있게 해줍니다.
REGISTER_MONOBEHAVIOR_METHOD 매크로
이 매크로는 MonoBehavior 파생 클래스의 메서드를 MethodRegistry에 등록하는 과정을 간소화합니다:
클래스와 메서드 이름으로 고유한 키를 생성
함수 포인터를 생성하여 이 키에 등록
정적 변수를 통해 프로그램 시작 시 자동으로 등록되도록 함
이벤트 함수 탐색 및 실행 메커니즘
이 함수는 애니메이터가 부착된 게임 오브젝트에서 사용 가능한 모든 이벤트 함수 목록을 생성합니다:
게임 오브젝트에 부착된 모든 컴포넌트를 검색
MonoBehaviour 파생 컴포넌트만 필터링
각 컴포넌트의 클래스 이름을 가져옴
등록된 모든 메서드 중 해당 클래스에 속하는 메서드만 필터링하여 목록에 추가
함수 실행: InvokeAnimationEvent
이 함수는 등록된 이벤트 함수를 실행합니다:
MethodRegistry에서 함수 키에 해당하는 함수 포인터를 가져옴
함수가 존재하면 MonoBehaviour 객체를 인자로 전달하여 실행
애니메이션 재생 중 이벤트 처리
이 코드는 다음 작업을 수행합니다:
현재 재생 중인 클립의 모든 이벤트를 순회
현재 애니메이션 진행률이 이벤트 시간에 도달했는지 확인
아직 호출되지 않은 이벤트라면 InvokeAnimationEvent를 통해 함수 호출
호출 후 isFuctionCalled 플래그를 true로 설정하여 중복 호출 방지
애니메이션 루프 시 이벤트 리셋
이 코드는 애니메이션이 마지막 프레임에 도달했을 때:
클립의 isEndFrame 플래그를 true로 설정
모든 이벤트의 isFuctionCalled 플래그를 false로 리셋하여 다음 루프에서 다시 호출될 수 있도록 함
반복 재생을 위해 프레임 인덱스를 초기화(isLoop가 true인 경우)
Last updated