[Unity VR과 Android BLE] #10 Volume 조절 및 Touchpad Swipe

in #kr-dev6 years ago (edited)

Unity VR앱과 안드로이드 앱을 integration하는 앱을 만들어 봅니다. 또 안드로이드의 BLE 장치 제어를 Unity에서 하는 내용을 다룹니다.


출처: https://medium.com/@narendrapal39/android-add-support-library-for-unity-205b45ca243d

이전글 - [Unity VR과 Android BLE] #9 Unity에서 BLE 장치 제어


이번에는 VR 재생할 때 볼륨을 조절하는 기능을 추가해 보겠습니다. 볼륨 조절 입력은 아래 그림과 같이 Gear VR의 터치패트를 이용할 것입니다.

출처: docs.unrealengine.com

터치패드를 아래로 쓰윽 훑으면, 즉 Swipe Down하면 볼륨을 작게 만들고, 위로 쓰윽 훑으면, 즉 Swipe Up하면 볼륨을 크게 만들어 보겠습니다.

이것도 두 가지 방법이 있습니다. 하나는 Unity의 Video Player의 Volume값을 조절하는 것이 있고, 다른 하나는 안드로이드 폰 자체의 볼륨을 조절하는 방법이 있습니다. 저는 안드로이드 폰의 볼륨을 조절하는 방법으로 해보겠습니다.

안드로이드 볼륨 조절 코딩

안드로이드 폰의 볼륨 조절하는 것은 매우 간단합니다. AudioManager를 사용하면 됩니다.
참고: https://android--code.blogspot.com/2017/08/android-set-media-volume.html

안드로이드 라이브러리 BLEControl.java파일에 다음과 같이 코드를 추가합니다.

public class BLEControl {
    생략
    // Audio manager
    private AudioManager audio_manager_;
    생략
    // get audio manager instance
    public void getAudioManager() {
        // Get the audio manager instance
        audio_manager_= (AudioManager)current_activity_.getSystemService(AUDIO_SERVICE);
    }

    // control media volume
    public void controlMediaVolume( final boolean _up ) {
        int max_volume = audio_manager_.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        int current_volume = audio_manager_.getStreamVolume(AudioManager.STREAM_MUSIC);
        int target_volume= current_volume;
        if( _up ) {
            if (++target_volume > max_volume)
                target_volume = max_volume;
        }
        else
        {
            if( --target_volume < 0 )
                target_volume= 0;
        }

        audio_manager_.setStreamVolume(
                AudioManager.STREAM_MUSIC, // Stream type
                target_volume, // Index
                AudioManager.FLAG_PLAY_SOUND // Flags
        );
    }
   생략

코드는 별거 없습니다. AudioManager 인스턴스를 얻어서 미디어 볼륨값을 설정하는게 다 입니다. Unity에서 Volume Up 인자가 넘어오면 controlMediaVolume함수에서 볼륨을 키우고, 아니면 볼륨을 낮춥니다. 볼륨 조절은 아래 함수를 사용합니다.

audio_manager_.setStreamVolume(
                AudioManager.STREAM_MUSIC, // Stream type
                target_volume, // Index
                AudioManager.FLAG_PLAY_SOUND // Flags
        );

별거 없죠?
Unity의 Video Player의 Volume 속성을 이용하는 것도 쉽습니다. 속성값과 터치패드 입력을 연결만 시켜주면 됩니다.

터치패드 입력

터치패드 입력도 매우 간단합니다. 사실 간단한 것은 이미 Oculus 패키지에 구현이 도어 있기 때문입니다. 여기서는 Oculus 패키지의 기능을 이용하겠습니다. Unity는 기본적으로 Input이라는 입력 클래스를 제공하지만 Swipe은 제공하지 않는 것 같습니다.

Start 함수 수정

Unity의 AndroidWrapper.cs 파일에서 아래와 같이 Start 함수 안에 AudioManager의 인스턴스를 얻어 오는 코드를 추가합니다. 방금 전에 만든 안드로이드 라이브러리 함수를 호출한느 것입니다.

void Start()
    {
        // Retrieve current Android Activity from the Unity Player
        AndroidJavaClass jclass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject activity = jclass.GetStatic<AndroidJavaObject>("currentActivity");

        // Pass reference to the current Activity into the native plugin,
        // using the 'setActivity' method that we defined in the ImageTargetLogger Java class
        GetJavaObject().Call("setActivity", activity);

        // get audio manager
        GetJavaObject().Call("getAudioManager");
        
        // connect to the paired BLE device
        Message.text = GetJavaObject().Call<string>("connectExternal");
    }

Update 함수 수정

AndroidWrapper.cs 파일의 Update함수를 아래와 같이 수정합니다. 편의상 입력을 처리하는 별도의 함수를 만들고 Update 함수에서 호출하는 방식으로 했습니다. 그리고 Unity의 Input 클래스를 사용하지 않고, OVRInput 클래스를 사용했습니다. Swipe의 경우는 매우 간단하게 사용할 수 있어서 편합니다.

// Update is called once per frame
    void Update()
    {
        HandleInputs();
    }

    // hande inputs
    void HandleInputs()
    {
        // tap on touch pad
        if( OVRInput.GetDown(OVRInput.Button.One) )
        {

        }

        // back button pressed
        if (OVRInput.GetDown(OVRInput.Button.Two))
        {
            // recenter the content to the current view
            InputTracking.Recenter();
        }

        // swipe up
        if (OVRInput.GetDown(OVRInput.Button.DpadUp))
        {
            // volume down
            GetJavaObject().Call("controlMediaVolume", true);
        }

        // swipe down
        if (OVRInput.GetDown(OVRInput.Button.DpadDown) )
        {
            // volume down
            GetJavaObject().Call("controlMediaVolume", false );
        }
    }

코드의 내용은 직관적입니다. Gear VR의 터치패드를 Swipe Up, Down 하면 볼륨 조절하는 안드로이드 라이브러리 함수를 호출합니다. 그리고 터치패드의 Back 버튼(또는 Return 버튼)을 클릭하면 영상을 현재 사용자의 시점 기준으로 맞추는 기능도 추가했습니다. 그것이 바로 InputTracking.Recenter()입니다. InputTracking을 사용하기 위해서는 AndroidWrapper.cs 파일에 다음 내용을 추가해야 합니다.

using UnityEngine.XR;

터치패드를 단순히 터치할 때 발생하는 이벤트, 즉 Button.One의 경우는 비워 뒀습니다. 적당한 용도로 사용하면 되겠습니다. 그러나 Swipe와 충돌의 위험이 있을 수 있습니다. 터치(또는 탭)을 먼저 처리하려면 함수에서 먼저 처리해 주면 될거 같네요. 직접 해보니 문제없이 터치(탭)과 Swipe 모두 잘 동작합니다. 위에서 나오지 않은 입력 방법도 있습니다. Swipe Right, Swipe Left 등도 추가할 수 있습니다. 다음 사이트를 참고하세요.
https://developer.oculus.com/documentation/unity/latest/concepts/unity-ovrinput/

결과 확인

Unity에서 Build and Run을 클릭하여 앱을 안드로이드 폰에 설치합니다.

역시나 VR앱이라서 결과 화면을 캡쳐 할 수 없어서 안타깝습니다. 실행해 본 결과 Swipe Up, Down하면 볼륨 화면에 볼륨 UI가 자동으로 표시됩니다. 매우 좋네요. Unity의 Volume 속성을 이용하면 이렇게는 안될 것입니다. 따로 슬라이드 UI를 만들어 줘야 하지만 안드로이드의 볼륨 조절 기능을 사용하니 UI도 자동으로 표시해 주니 매우 만족스럽습니다.


시리즈 글은 이정도로 일단락 짓겠습니다. 복수의 페어링 장치가 있을 때 이슈가 있지만 나중에 기회되면 해결해 보는 걸로 하겠습니다. 다음에는 Unity로 좀 엉뚱한 3D 게임을 하나 만들어 볼까 합니다. 이런 느낌인데, 좀 차분한걸로요. 아.. 그리고 훨씬 간단하게요 ^^;

자, 이제 VR 동영상 재생과 안드로이드 라이브러리 사용하는 것은 어렵지 않게 할 수 있게 됐습니다.

오늘의 실습: VR 동영상 재생과 안드로이드 라이브러리 기본 구현을 완료됐으니, 이제 멋진 VR앱을 만들어 보세요~

Coin Marketplace

STEEM 0.19
TRX 0.15
JST 0.029
BTC 63549.46
ETH 2562.53
USDT 1.00
SBD 2.66