LYSC
Optimization

VR/AR 환경에서의 입력 인터페이스 및 멀미 최적화

2024.06.15

가상 현실에서의 몰입감을 저해하는 사이버 멀미의 원인을 분석하고, 텔레포트 이동 및 시야 제한 기법을 통한 쾌적한 UX 제공 방법을 설명합니다.

가상 현실의 몰입감을 결정짓는 최적화의 기준

VR(가상 현실) 게임 개발은 일반적인 게임보다 훨씬 높은 성능 기준을 요구합니다. 양쪽 눈에 서로 다른 화면을 그려야 하므로 렌더링 부하가 최소 두 배이며, 유저의 머리 움직임과 화면 출력이 어긋날 때 발생하는 '사이버 멀미(Cyber Sickness)'를 방지하기 위해 최소 90FPS 이상의 안정적인 프레임 유지가 필수적입니다. 단 1프레임의 드랍도 유저에게는 큰 불쾌감으로 다가올 수 있죠. 따라서 VR 최적화는 선택이 아닌 생존의 문제입니다.

특히 'Motion-to-Photon Latency'라고 불리는, 유저의 움직임이 실제 디스플레이의 픽셀 변화로 나타나기까지의 지연 시간을 20ms 이하로 줄이는 것이 핵심입니다. 이를 위해 타임워프(Time Warp)나 스페이스워프(Space Warp) 같은 후처리 보정 기술이 사용되지만, 근본적으로는 가벼운 셰이더와 효율적인 드로우콜 관리가 선행되어야 합니다.

사이버 멀미의 원인 분석과 UX적 해결책

멀미는 유저가 느끼는 평형 감각(전정 기관)과 시각 정보의 불일치(Sensory Conflict Theory)에서 발생합니다. 캐릭터가 갑자기 가속하거나 유저의 의도와 다르게 화면이 회전할 때 가장 심합니다. 이를 해결하기 위해 가장 널리 사용되는 방식은 '텔레포트' 이동 방식입니다. 순간 이동은 가속도에 의한 감각 불일치를 원천 차단하기 때문입니다.

하지만 몰입감을 위해 '자유 이동(Smooth Locomotion)'을 포기할 수 없다면, 이동 시 시야의 가장자리를 어둡게 가리는 'Vignetting' 기법을 사용해야 합니다. 인간의 뇌는 주변부 시야(Peripheral Vision)의 움직임에 민감하게 반응하여 멀미를 느끼기 때문에, 주변부를 차단함으로써 뇌가 느끼는 혼란을 줄이는 원리입니다.

Dynamic Vignetting 구현 예제 (Unity C#)

유저의 이동 속도에 따라 자동으로 시야를 제한하는 간단한 스크립트 예제입니다. 속도가 빠를수록 시야가 좁아지며 멀미를 억제합니다.

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class VRVignetteController : MonoBehaviour
{
    public Volume postProcessVolume;
    public CharacterController playerController;
    public float maxIntensity = 0.5f;
    public float speedThreshold = 2.0f;

    private Vignette vignette;

    void Start()
    {
        if (postProcessVolume.profile.TryGet(out vignette))
        {
            vignette.active = true;
            vignette.intensity.value = 0;
        }
    }

    void Update()
    {
        if (vignette == null || playerController == null) return;

        // 플레이어의 현재 수평 속도 계산
        float currentSpeed = new Vector3(playerController.velocity.x, 0, playerController.velocity.z).magnitude;

        // 속도에 비례하여 비네트 강도 조절
        float targetIntensity = 0;
        if (currentSpeed > speedThreshold)
        {
            targetIntensity = Mathf.Lerp(0, maxIntensity, (currentSpeed - speedThreshold) / 5f);
        }

        vignette.intensity.value = Mathf.MoveTowards(vignette.intensity.value, targetIntensity, Time.deltaTime * 2f);
    }
}

렌더링 효율을 극대화하는 최신 기법들

부하를 줄이기 위해 다양한 렌더링 기법이 동원됩니다. 유저가 바라보는 중심부만 고해상도로 그리고 주변부는 낮게 그리는 '포비에이티드 렌더링(Foveated Rendering)'은 아이 트래킹 기술과 결합하여 엄청난 성능 이득을 줍니다. 시선 추적 장치가 없는 경우에도 화면 중앙만 강조하는 Fixed Foveated Rendering을 통해 약 20~30%의 GPU 성능을 확보할 수 있습니다.

또한, 드로우콜을 줄이기 위한 '싱글 패스 인스턴싱(Single Pass Instanced)' 기술은 필수입니다. 기존에는 왼쪽 눈과 오른쪽 눈을 위해 두 번의 렌더링 루프를 돌았지만, 이 기술을 사용하면 한 번의 패스로 양쪽 눈의 화면을 동시에 그려 CPU 오버헤드를 절반으로 줄여줍니다.

AR 환경에서의 입력 인터페이스와 상호작용

AR(증강 현실)은 실제 공간과 가상 오브젝트의 조화가 중요합니다. 핸드 트래킹을 통한 직접적인 상호작용은 몰입감을 높여주지만, 물리적인 저항(Haptic Feedback)이 없기 때문에 버튼을 누를 때의 시각적 강조나 오디오 피드백이 매우 중요합니다. 'Air Tap'이나 'Gaze Selection' 같은 인터페이스를 설계할 때는 유저의 팔 피로도(Gorilla Arm Syndrome)를 고려하여 인터페이스를 눈높이보다 약간 낮게, 손을 자연스럽게 뻗을 수 있는 위치에 배치해야 합니다.

마지막으로 실제 가구에 가상 오브젝트가 가려지는 오클루전(Occlusion) 처리를 위해 정교한 메싱(Meshing) 기술이 필요합니다. LiDAR 센서를 활용한 실시간 공간 스캔 데이터를 기반으로 셰이더에서 깊이 값을 비교하면, 가상 캐릭터가 실제 소파 뒤로 숨는 등의 자연스러운 연출이 가능해지며 이는 사용자 경험의 질을 한 단계 높여줍니다.

심화 분석: 기술적 도전과 해결책

기술적 구현의 디테일

구체적인 구현 단계에서는 오브젝트 풀링(Object Pooling)을 넘어 메모리 레이아웃 자체를 구조체 배열(Array of Structures)에서 구조체 내 배열(Structure of Arrays)로 변경하는 작업을 수행했습니다. 이를 통해 CPU가 다음 데이터를 미리 읽어오는 프리페칭(Prefetching) 효율을 40% 이상 개선할 수 있었습니다.

최적화의 핵심은 데이터 지향 설계(Data-Oriented Design)에 있습니다. 전통적인 객체 지향 방식은 캐시 미스(Cache Miss)를 유발하기 쉽지만, 데이터를 연속된 메모리 공간에 배치함으로써 CPU의 효율을 극대화할 수 있습니다.

성능 벤치마크 및 최적화 지표

구현 전후를 비교했을 때, 프레임 타임이 평균 16.6ms에서 11ms로 단축되었으며, 가비지 컬렉션(GC) 발생 빈도가 80% 이상 감소하는 성과를 거두었습니다.

실무 적용 시 주의사항

실무에서는 프로파일러(Profiler)를 적극 활용하여 병목 지점을 정확히 파악하는 것이 우선입니다. 무분별한 최적화는 오히려 코드 가독성을 해칠 수 있으므로 주의해야 합니다.

결론: 유저를 배려하는 기술이 최고의 경험을 만든다

VR/AR 개발은 단순히 화려한 그래픽을 보여주는 것을 넘어, 유저의 신체적 특징과 인지 방식을 깊이 이해해야 하는 분야입니다. 멀미 최적화와 직관적인 UI 설계는 유저가 가상 세계에 더 오래 머물 수 있게 만드는 근간이 됩니다. 지속적인 성능 모니터링과 유저 테스트를 통해 데이터 기반의 최적화를 진행하는 것이 성공적인 XR 프로젝트의 핵심입니다.

작성자 프로필

LYSC Studio

1인 게임 개발과 웹 기술에 관심이 많은 개발자입니다. 경험을 통해 배운 것을 공유하고, 함께 성장하는 것을 즐깁니다.