Unity에서 플랫폼 모드 이동

플랫폼 모드를 이동하면 HoloLens 2 선박, 석유 플랫폼 및 기타 차량과 같은 이동 플랫폼에서 올바르게 작동할 수 있습니다.

플랫폼 모드 이동에 대한 자세한 정보

개념적 개요

혼합 현실 시스템이 제대로 작동하려면 환경을 기준으로 헤드셋을 추적해야 합니다. 이 상대 추적을 사용하면 헤드셋 사용자가 환경에서 단단히 잠겨 있는 것처럼 보이도록 그래픽을 렌더링할 수 있습니다. 추적은 일반적으로 외부의 카메라와 IMU(관성 측정 단위)의 측정값을 사용하여 계산된 포즈를 결합하여 수행됩니다. 이 메서드는 환경이 참조의 관성 프레임에 있을 때 잘 작동합니다. 행성의 움직임과 같은 작은 효과는 일반적으로 무시됩니다.

환경이 참조의 관성 프레임에 없는 경우 일반 헤드 추적 시스템이 실패합니다. 이동 플랫폼 모드 기능은 관성 프레임을 기준으로 환경의 동작을 고려하여 이 문제를 해결합니다. 따라서 플랫폼 모드 이동 시 HoloLens 2 환경에 고정된 것처럼 보이는 홀로그램을 렌더링할 수 있습니다.

이동 플랫폼 모드를 활성화하려면 어떻게 해야 하나요?

다양한 사용 사례를 가능하게 하기 위해 이동 플랫폼 모드를 활성화하는 다양한 방법이 제공되었습니다. 어떤 방법을 선택할지 신중하게 고려하는 것이 중요합니다. 핵심 질문은 'HoloLens 2가 현재 이동 플랫폼 내에 있는지 누가 아는가?'입니다. 예제는 다음 표를 참조하세요.

HL2가 이동 플랫폼에 있는지 누가 아는가 이동 플랫폼 모드를 설정하는 가장 좋은 방법 이점 비용
시스템 관리자 모바일 장치 관리 사용자가 관여할 필요가 없습니다. 모든 앱은 수정 없이 작동합니다. 디바이스가 잘못된 모드로 전환되는 것을 방지할 수 있습니다. 사용자 및 앱은 모드를 변경할 수 없습니다.
최종 사용자 설정 앱 사용자는 종종 디바이스를 사용하는 시기와 장소에 대해 가장 잘 알고 있습니다. 모든 앱은 수정 없이 작동합니다. 사용자는 모드가 있는지 모를 수 있습니다.
애플리케이션 이 문서에 설명된 SDK를 사용합니다. 환경을 미리 알 수 없는 경우 사용 사례별 큐를 사용하여 모드를 전환할 수 있습니다. 사용자가 이 결정을 내리고 설정에서 모드를 변경해야 하는 요구 사항을 제거합니다. 잘못 설계된 앱은 매우 나쁜 경험을 제공하고 디바이스를 예기치 않은 모드로 전환할 수 있습니다.

플랫폼 모드 이동에 대한 모범 사례

주 서버 설명
사용자 선택 존중 해당 모드를 변경하기 전에 사용자에게 선택 사항을 제공해야 하며 앱의 런타임에 대한 해당 선택을 계속 준수해야 합니다.
사용자에게 경고 제공 앱 시작/다시 시작 시 모드를 즉시 변경하지 않습니다. 이렇게 하면 디바이스에서 추적이 손실되는 이유를 알 수 없으므로 사용자 환경이 저하됩니다.
변경 모드 최소화 이동 플랫폼 모드 설정을 변경하면 디바이스에서 추적이 손실되어 부정적인 사용자 환경이 발생합니다. 따라서 모드를 변경하는 빈도를 최소화하는 것이 좋습니다. 이상적으로는 디바이스가 고정 환경에서 이동 환경으로 전환하거나 그 반대로 전환하는 경우에만 모드가 변경됩니다.
환경에 대해 확실하지 않은 경우 플랫폼 모드 이동 사용 플랫폼 모드 이동은 고정된 환경과 이동 환경에서 모두 작동할 수 있습니다. 일반 추적 알고리즘은 고정 환경에서만 작동하므로 환경이 이동하는지 확실하지 않은 경우 이동 플랫폼 모드를 선택하는 것이 더 안전한 선택이 될 수 있습니다.
알려진 고정 환경에서 플랫폼 모드 이동 사용 안 함 플랫폼 모드 이동은 고정 환경에서 표준 모드보다 성능이 떨어지게 됩니다. 이는 작은 성능 저하이지만 대부분의 사용자에게는 눈에 띄게 됩니다.
디바이스를 종료할 모드를 고려합니다. 이 SDK를 통해 개발자는 디바이스의 부팅 전체에서 강력한 환경을 디자인할 수 있습니다. 디바이스가 다음에 부팅될 때 이동 플랫폼에 있는지 확인하고 디바이스를 적절한 모드로 유지합니다.

SDK는 어디서 얻을 수 있나요?

이동 플랫폼 SDK는 개발자가 Win32 또는 UWP 플랫폼용 애플리케이션을 개발할 수 있도록 C# 및 C++에 대한 언어 프로젝션을 지원합니다. Mixed Reality 기능 도구를 사용하여 SDK를 다운로드하고 설치합니다.

이 SDK 사용 어떻게 할까요?

SDK를 설치한 후 다음과 같이 MovingPlatformManger를 사용하도록 스크립트를 설정할 수 있습니다.

// Top of file
using Microsoft.MixedReality.MovingPlatform;
// Code body
m_movingPlatformManager = new MovingPlatformManager();

현재 모드 읽기

모드의 현재 값은 다음과 같이 읽을 수 있습니다.

MovingPlatformMode currentMode = m_movingPlatformManager.Mode;

MovingPlatformMode는 다음과 같이 정의된 열거형입니다.

public enum MovingPlatformMode
{
    Standard,                // The legacy mode that devices use out-of-the-box.
    MovingPlatformOptimized  // Allows tracking on moving platforms.
}

VR 장치 및 HoloLens 1과 같이 이동 플랫폼 모드를 사용할 수 없는 디바이스는 항상 '표준'을 반환합니다.

모드 설정

다음과 같이 이동 플랫폼 모드 값을 설정할 수 있습니다.

bool success = m_movingPlatformManager.TrySetMode(MovingPlatformMode.MovingPlatformOptimized);

디바이스 모드가 이제 요청된 모드와 일치하면 TrySetMode가 true를 반환합니다. 모드가 이미 원하는 상태인 경우 아무 작업도 수행되지 않으며 디바이스에서 추적이 손실되지 않습니다.

모드 변경 시 콜백

경우에 따라 다른 앱 또는 사용자가 이동 플랫폼 모드 값을 변경했는지 여부를 아는 것이 유용할 수 있습니다. 다음과 같이 이 작업을 수행할 수 있습니다.

// Code Body
m_movingPlatformManager.ModeChanged += CallbackOnMPMChanged;
...
void CallbackOnMPMChanged(object sender, MovingPlatformEventArgs args)
{
    movingPlatformModeChanged = true;
    movingPlatformModeValue = args.ModeEntered;
}
...
void Update()
{
    // It's not reccomended to do work in the callback.
    if (movingPlatformModeChanged)
    {
        movingPlatformModeChanged = false;
        // Do some work
    }
}

모드를 설정할 수 있는지 확인

경우에 따라 모드를 변경하기 전에 모드를 설정할 수 있는지 여부를 파악하는 것이 유용합니다. 예를 들어 사용자에게 기본 설정을 요청하는 값이 있는지 알고 싶은 경우입니다. IsSetModeSupported 함수를 사용하여 플랫폼 모드를 이동할 수 있는지 확인할 수 있습니다.

bool supported = m_movingPlatformManager.IsSetModeSupported();

이 함수는 디바이스가 모드를 변경할 수 있는 경우 true를 반환하고, 가능하지 않은 경우 false를 반환합니다. 이 함수는 MDM(모바일 장치 관리) 정책을 고려합니다. 예를 들어 MDM이 MovingPlatformMode를 "On"으로 강제 적용하면 이 함수는 false를 반환합니다.

데모 스크립트

이 스크립트는 SDK의 모든 중요한 요소를 한 곳에 보여줍니다. 이 예제는 위에 표시된 모범 사례를 따르지 않습니다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.MovingPlatform;
using System;

public class MovingPlatformDemo : MonoBehaviour
{
    public GameObject cube; // A simple cube to display colors.
    private MovingPlatformManager m_movingPlatformManager;
    private Renderer cubeRenderer;
    private bool movingPlatformModeChanged;
    private MovingPlatformMode movingPlatformModeValue;

    // Start is called before the first frame update
    void Start()
    {
        m_movingPlatformManager = new MovingPlatformManager();
        cubeRenderer = cube.GetComponent<Renderer>();

        // Get initial value of mode, 
        // Just this mechanism would be adequate if a one time check is acceptable. 
        MovingPlatformMode initialMovingPlatformMode = m_movingPlatformManager.Mode;

        // Find if It's possible to change the mode. 
        bool isSettable = m_movingPlatformManager.IsSetModeSupported();

        // Here you would add some use case specific logic using initialMovingPlatformMode and isSettable
        // to decide if you should ask the user if they want to change the mode. 

        // To set the mode.
        bool success = m_movingPlatformManager.TrySetMode(MovingPlatformMode.MovingPlatformOptimized);

        // Visual indicator of current state: Green = Moving Platform Optimized, Red = Regular.
        SetColourFromState(m_movingPlatformManager.Mode, cubeRenderer);

        // We set a callback to be notified if there's a change in mode. This is typically optional.
        m_movingPlatformManager.ModeChanged += CallbackOnMPMChanged;
        movingPlatformModeChanged = false;
    }

    // Update is called once per frame
    void Update()
    {
        // This must be done in the UI thread.
        if (movingPlatformModeChanged)
        {
            movingPlatformModeChanged = false;
            SetColourFromState(movingPlatformModeValue, cubeRenderer);
        }
    }

    // Sets renderer to:
    // Green = Moving Platform Mode Enabled
    // Red = Moving Platform Mode Disabled
    void SetColourFromState(MovingPlatformMode mode, Renderer thisRend)
    {
        if (mode == MovingPlatformMode.MovingPlatformOptimized)
        {
            thisRend.material.color = new Color(0f, 1f, 0f, 1f);
        }
        else
        {
            thisRend.material.color = new Color(1f, 0f, 0f, 1f);
        }
    }

    void CallbackOnMPMChanged(object sender, MovingPlatformEventArgs args)
    {
        movingPlatformModeChanged = true;
        movingPlatformModeValue = args.ModeEntered;
    }
}

참고 항목