Add Object to bone

게임 개발에서 스켈레탈 애니메이션은 캐릭터 표현에 필수적이지만, 모든 뼈를 매 프레임 업데이트하는 것은 상당한 연산 비용이 듭니다. 이 프로젝트에서는 필요한 뼈만 업데이트하는 방식을 통해 최적화를 하였습니다.

최적화 접근법: "필요한 뼈만 업데이트"

일반적인 캐릭터 모델에는 수십 또는 수백 개의 뼈가 있지만, 이 중 많은 뼈는 내부 구조용으로만 사용되고 실제로 외부 객체가 부착되지 않습니다. 이 프로젝트에서는 다음 원칙을 적용했습니다:

"UI상에서 선택한 오브젝트, 뼈들 중 뼈가 아닌 GameObject가 자식으로 들어있는 뼈만 Update하도록 하자!"

이 접근법을 구현하기 위해 사용된 시스템을 분석해 보겠습니다.

관련 데이터 구조 (GameObject 클래스)

관련 접근자/설정자 메서드:

Animator에서의 뼈 업데이트 로직

Animator::UpdateBoneTransforms() 함수는 성능 최적화의 핵심입니다:

이 함수의 핵심은 GetGameObject()->GetActiveBoneIndices()에서 반환하는 뼈 인덱스만 업데이트한다는 점입니다. 모든 뼈가 아닌, 활성화된 뼈만 처리함으로써 상당한 성능 이득을 얻을 수 있습니다.

계층 구조 관리와 활성 뼈 등록

GUIManager::HandleBoneObjectParenting 함수는 계층 구조가 변경될 때 활성 뼈를 관리합니다:

이 함수는 다음과 같은 중요한 작업을 수행합니다:

  1. 자식 객체가 뼈 객체의 하위로 배치될 때 호출됩니다.

  2. 부모가 뼈 객체인 경우:

    1. 루트 모델 객체(BoneParentObject)의 활성 뼈 목록에 이 뼈의 인덱스를 추가합니다.

    2. 자식이 뼈가 아니라면 부모 뼈의 _hasNonBoneChildren 플래그를 설정합니다.

    3. 자식에게 부모 뼈 참조를 설정합니다(SetNonBoneChildrenParent).

활성 뼈 인덱스 관리 흐름

이 시스템의 전체 흐름은 다음과 같습니다:

최적화 효과 분석

이 접근법은 다음과 같은 중요한 최적화 효과를 제공합니다:

  1. 선택적 뼈 업데이트: 모든 뼈가 아닌, 실제로 필요한 뼈만 업데이트합니다.

    1. 일반적인 모델에서 100개의 뼈가 있을 때, 실제로 외부 객체가 붙은 뼈는 10-20개 정도일 수 있습니다.

    2. 90%의 뼈 업데이트 연산을 절약할 수 있습니다.

  2. 자동 활성화: 객체가 뼈에 부착될 때 해당 뼈와 그 상위 계층이 자동으로 활성화됩니다.

    1. 수동으로 어떤 뼈를 업데이트할지 관리할 필요가 없습니다.

  3. 계층적 관계 유지: 실제 계층 구조는 그대로 유지하면서 업데이트만 최적화합니다.

    1. 이를 통해 애니메이션 품질 저하 없이 성능 향상을 얻을 수 있습니다.

Last updated