OvrAvatarManager
OvrAvatarManager는 SDK의 생명주기(LifeCycle)를 관리하며, 주요 API를 제공하는 싱글톤 컴포넌트로써 중앙 설정 관리 역할을 수행하며 다음 기능들을 제공합니다.
아바타 로드 속도 및 동시 실행 제한 등을 제어하여 프레임 속도를 유지합니다.
네트워크 대역폭 설정으로 로드 시간을 조정합니다.
-1로 설정하면 대역폭 제한이 없으며, 설정 값을 낮추면 로드 시간이 증가할 수 있습니다.
아바타 로드를 빠르게 하기 위해 자산(Avatar Asset)을 미리 로드합니다.
Asset Preload는 로드 속도를 높이는 대신 메모리 사용량이 증가합니다.
로그 레벨 설정으로 SDK 디버깅을 지원합니다.
스키닝 솔루션 및 각 LOD에 대한 품질 설정을 지원합니다.
사용하지 않는 Skinning을 비활성화하여 로딩 시간 및 런타임 메모리 사용량을 최적화할 수 있습니다.
AvatarLODManager
AvatarLODManager는 LOD(수준별 세부화) 시스템의 핵심 구성 요소입니다. 컬링(culling), 성능 조정, 동적 성능 조정, 중요도 기반 LOD 전환을 처리합니다.
Refresh Seconds: LOD가 다시 계산되는 간격을 조정합니다. 기본값을 사용하는 것이 권장됩니다.
Extra Cameras: 추가 카메라를 LOD 계산에 포함하려면 이 배열에 카메라를 추가합니다.
아바타가 화면 밖으로 나가면 기본적으로 메시 컴포넌트가 비활성화됩니다. 이로 인해 해당 게임 오브젝트에 연결된 다른 스크립트도 중지됩니다.
JointTypesToCullOn은 컬링 계산에 사용할 아바타 조인트를 지정합니다.
동적 성능 시스템은 씬 내 아바타의 수와 중요도를 고려하여 LOD 값을 계산합니다.
Max Vertices to Skin은 값을 높이면 아바타의 LOD 품질이 향상되지만 프레임 렌더링 시간이 증가합니다.
기본값을 유지하거나 성능 요구 사항에 따라 조정합니다.
GPUSkinningConfiguration
GPUSKinningConfiguration컴포넌트는 GPU 스키닝과 관련된 품질 설정을 관리하는 구성 요소입니다.
각 LOD에 대해 개별적인 스키닝 품질을 설정할 수 있으며, 기본값은 Bone 4로 설정되어 있고 이는 가장 높은 품질 옵션입니다.
낮은 품질의 LOD에 낮은 스키닝 품질을 설정하면 성능이 향상되지만 스키닝 아티팩트가 발생할 수 있습니다.
GPU 스키닝을 사용하는 경우 특정 조인트에 객체를 부착하려면 CriticalJointTypes에 해당 조인트를 추가해야 합니다.
CriticalJointTypes는 명시된 조인트 및 해당 부모 계층 구조의 변환만 업데이트합니다.
모든 Critical Joint Transform은 OvrAvatarEntity의 기본 Transform에 직접 연결됩니다.
SampleInputManager
SampleInputManager는 기본 입력 관리자로, OVRInput을 네이티브 SDK로 전달하는 역할을 합니다. 커스터마이징이 필요하면 이 컴포넌트를 OvrAvatarInputManager를 상속한 스크립트로 교체할 수 있습니다. (전 아직 필요성을 모르겠지만..)
비동기 본체 솔버 사용 (Use Async Body Solver)는 본체 솔버 시스템이라는 이름으로, 메인 스레드 대신 비동기 실행을 가능하게 해줍니다. CPU 성능 향상을 기대할 수 있지만, 평균적으로 1 프레임의 추가 지연이 발생할 수 있습니다. (근데, 최신버전에는 해당 옵션이 안보이네요..?)
OvrAvatarShaderManager
OvrAvatarShaderManager는 아바타가 사용하는 셰이더 구성 정보를 포함하는 컴포넌트입니다. 셰이더 커스터마이징이 필요한 경우 이 구성 요소를 대체할 수 있습니다.
Shader Manager(OvrAvatarShaderManager)는 아바타 로드 시 사용되는 셰이더 제공에 초점을 맞춘 구성 요소입니다. OvrAvatarManager의 인스턴스와 함께 사용되며, 로드된 후에는 거의 비활성화 상태로 남아 있습니다.
아바타 로드 시 Shader Manager에 정의된 셰이더 설정을 기반으로 머티리얼 생성이 이루어지기에, 로드 후에는 Shader Manager를 사용해 머티리얼을 조작할 수 없습니다.
추천 방법은 애플리케이션 전용 머티리얼 프로퍼티 블록 또는 메시 렌더러의 SharedMaterial을 사용하여 변경하는 것입니다.
Meta Avatars Editor Integration Overview
Meta Avatars Editor는 사용자가 VR 애플리케이션 내에서 자신의 아바타를 편집 및 커스터마이징할 수 있도록 하는 기능입니다. SDK v29 이상을 사용해야 최신 VR 편집기를 애플리케이션에 통합할 수 있습니다.
LaunchAvatarEditor() 메서드를 호출하여 편집기로의 딥 링크를 설정합니다.
public class OpenAvatarEditor : MonoBehaviour
{
void Update()
{
if (OVRInput.GetDown(OVRInput.Button.Start, OVRInput.Controller.LTouch | OVRInput.Controller.LHand))
{
AvatarEditorDeeplink.LaunchAvatarEditor();
}
}
아바타 변경 사항을 주기적으로 확인하여 멀티플레이 환경에서 다른 사용자의 업데이트나 외부 디바이스(예: 스마트폰)에서 편집한 내용을 반영합니다. 참고 코드 - SampleAvatarEntity.cs를 확인하시길 바랍니다.
Meta Avatars SDK 셰이더 가이드
Meta Avatars SDK는 아바타에 적용할 수 있는 다양한 셰이더를 제공합니다. 기본 제공되는 셰이더를 사용하거나, 특정 요구 사항에 따라 커스텀 셰이더를 구현할 수도 있습니다.
1. 기본 제공 셰이더
1) Diffuse
- 파일명: UnityMobile/Avatar-Mobile-Diffuse
- 성능: 가장 빠름
- 복잡도: 매우 낮음
- PBR: 지원하지 않음
- 조명 모델: Lambertian Diffuse Reflection
- 설명:
- 가장 단순한 셰이더.
- 보조 맵(secondary map)을 사용하지 않음.
- 빠른 성능을 요구하는 환경에 적합.
2) BumpSpec
- 파일명: UnityMobile/Avatar-Mobile-BumpSpec
- 성능: 빠름
- 복잡도: 낮음
- PBR: 지원하지 않음
- 조명 모델: 단순한 반사(gloss) 및 선택적 노말 맵
- 설명:
- Diffuse 셰이더와 유사하지만, 반사 강조를 위해 노말 맵을 추가로 사용 가능.
- Shininess 머티리얼 파라미터로 반사 강도를 제어.
3) Horizon
- 파일명: Horizon/Avatar-Horizon
- 성능: 중간
- 복잡도: 매우 높음
- PBR: 지원
- 조명 모델: Metallic-Roughness + SH Ambient + Reflection Map
- 설명:
- Meta Quest(최대 50명)와 Quest 2(최대 100명)에서 우수한 성능.
- Oculus Connect 2019와 FBConnect 2020에서 사용된 PBR 셰이더.
4) Standard
- 파일명: UnityStandard/Avatar-Standard
- 성능: 느림
- 복잡도: 높음
- PBR: 지원
- 조명 모델: Metallic-Roughness + SH Ambient + Reflection Map
- 설명:
- Unity의 Standard 셰이더를 이식.
- 높은 지시어(instruction) 수로 인해 VR 프로젝트에는 권장하지 않음.
5) Khronos
- 파일명: Khronos/Avatar-Khronos
- 성능: 느림
- 복잡도: 중간
- PBR: 지원
- 조명 모델: Metallic-Roughness + 텍스처 기반 Ambient Diffuse 및 Specular
- 설명
- glTF 규격에 따라 설계된 최초의 Meta Avatars 셰이더.
- 시각적 우수성과 코드 복잡성의 균형이 뛰어남.
- IBL 시스템과 결합하여 사용 가능.
Socket Attachables
Attachables 시스템은 오브젝트를 아바타에 동적으로 부착하고, 아바타의 크기에 따라 위치와 크기를 자동으로 조정할 수 있게 해줍니다. Attachables의 주요 기능에는 오브젝트를 아바타의 특정 위치(소켓)에 동적으로 부착하는 것과, 아바타 크기에 따라 오브젝트 위치 및 크기 자동 조정하는 것이 있습니다.
OvrAvatarSocketDefinition
- OvrAvatarSocketDefinition은 Attachables의 핵심 클래스입니다.
- 소켓을 구성하고 초기화하며, 아바타의 스켈레톤에 따라 소켓을 생성합니다.
사용 방법
1. Critical Joint 정의
- 소켓을 만들기 전에 Critical Joint를 아바타의 OvrAvatarEntity에 정의해야 합니다.
- Critical Joint가 정의되지 않으면 소켓이 생성되지 않습니다.
2. 소켓 생성
소켓은 다음 두 가지 방법으로 생성할 수 있습니다
- CreateSocket() 메서드
- AttachableSocket 컴포넌트 (Meta Avatar SDK v33 이상)
2-1. 코드로 소켓 생성
소켓 생성 최소 구성
// 아바타 엔터티 참조
OvrAvatarEntity avatarEntity = ...;
// 소켓 생성
OvrAvatarSocketDefinition chestSocket = avatarEntity.CreateSocket(
"MY_CHEST_SOCKET_NAME", // 소켓 이름 (유일해야 함)
CAPI.ovrAvatar2JointType.Chest, // 소켓을 연결할 Critical Joint
position: new Vector3(0f, 0f, 0f), // 소켓의 로컬 위치
eulerAngles: new Vector3(-90, 0, -90) // 소켓의 로컬 회전
);
2-2. 소켓 매개변수
파라미터 | 필수/옵션 | 설명 | 기본값 |
socketName | 필수 | 소켓 이름 (유일해야 함) | - |
jointType | 필수 | 소켓이 부착될 Critical Joint 유형 | - |
position | 필수 | Critical Joint 기준 소켓의 로컬 위치 | - |
eulerAngles | 필수 | 로컬 회전 | - |
baseScale | 옵션 | 오브젝트의 기본 스케일 | Vector3.one |
width | 옵션 | 아바타 크기에 따라 오브젝트 스케일을 동적으로 조정 | - |
depth | 옵션 | 아바타 크기에 따라 오브젝트 스케일을 동적으로 조정 | - |
height | 옵션 | 아바타 크기에 따라 오브젝트 스케일을 동적으로 조정 | - |
createGameObject | 옵션 | 소켓용 GameObject 생성 여부 | true |
scaleGameObject | 옵션 | 스케일 적용 여부 | false |
아래에 예제 있습니다.
2-3. 전체 구성 예제
OvrAvatarSocketDefinition chestSocket = entity.CreateSocket(
"MY_CHEST_SOCKET_NAME",
CAPI.ovrAvatar2JointType.Chest,
position: new Vector3(0f, 0f, 0f),
eulerAngles: new Vector3(-90, 0, -90),
baseScale: Vector3.one,
depth: 0.25f,
width: 0.4f,
height: null, // 높이 스케일 조정 없음
createGameObject: true,
scaleGameObject: false
);
3. AttachableSocket 컴포넌트 사용
- Unity 컴포넌트 방식: 소켓을 직접 추가하고 설정하는 방법.
AttachableSocket _generatedSocket;
_generatedSocket = entity.gameObject.AddComponent<AttachableSocket>();
_generatedSocket.SocketName = "ProgrammaticSocket";
_generatedSocket.JointType = CAPI.ovrAvatar2JointType.Chest;
_generatedSocket.BaseScale = new Vector3(30f, 30f, 30f);
_generatedSocket.Position = new Vector3(0.7f, 0.7f, 0.7f);
_generatedSocket.EulerAngles = new Vector3(30f, 30f, 0f);
4. 소켓 초기화
소켓 생성 후 초기화 필요한데 OvrAvatarEntity.OnUpdateAttachables()를 호출하여 초기화하면 됩니다.
초기화가 비동기적으로 진행되므로 IsReady() 메서드로 준비 상태를 확인하면 됩니다.
5. 오브젝트 부착
Attach() 메서드로 소켓에 오브젝트를 부착
void Update() {
if (chestSocket.IsReady()) {
chestSocket.Attach(someEquipmentGameObject);
}
}
다른 오브젝트를 부착하면 이전 오브젝트는 자동으로 분리됩니다
chestSocket.Attach(yellowBackpack); // 노란색 가방 부착
chestSocket.Attach(redBackpack); // 빨간색 가방 부착, 노란색 가방 분리
6. 수동으로 부모 설정
생성된 GameObject를 수동으로 부모로 설정 가능
var go = chestSocket.socketObj;
myEquipment.SetParent(go.transform, false);