이 포스팅 이후에 다시 플러그인을 개선시켜 결과물 갤러리에 포스팅 해두었습니다.
여기를 통해 확인 가능합니다.
DIY VR 컨트롤러를 만들던 도중에 아두이노에서 받은 여러 가지 센서값들 Unity/Unreal의 Android 프로젝트에서 받아 활용하기 위해서는 블루투스나 WIFI 모듈을 이용한 통신을 해야 한다. Unreal은 Unity와는 다르게 아직 생각보다 자료가 적어 난항을 겪다가 Unity로 먼저 예시를 만들기로 했다. (Unity로 하다보니 Unreal도 어떻게 접근해야 하는지 알겠다는 건 함정)
어쨌든, Unity Android 프로젝트에서 디바이스에 연결된 Bluetooth를 이용하기 위해서는 Plugin을 만드는 절차가 필요하다. 원래대로라면 JNI를 사용하여야 하지만, Unity가 이에 관련된 래퍼 클래스를 제공하고 있어 생각보다 손쉽게 Plugin을 만들 수 있었다.
그 방법은 바로 UnityJavaClass를 이용하는 방법이다. Bluetooth에 관련된 플러그인들이 이미 에셋 스토어를 통해 배포되고 있지만, 공부 목적으로 만들고 있으니 직접 제작해보기로했다. (이 방법과 JNI를 이용하는 방법을 익혀야 Unreal에서도 써먹을 수가 있지 크흠...)
준비작업
Unity Android Plugin을 제작하는데 필요한 물건들은 java class와 Manifest 파일 그것들과 인테그레이션되는 Unity 스크립트가 필요하다. 필요한 안드로이드 기능들과 UntiyPlayer를 이용하여 Unity와 인테그레이션된 java파일들을 jar로 패키징하여 Manifest와 함께 Plugins>Android 폴더에 집어넣게되면 사용 준비 끝!
주의할 점은 jar로 패키징할때 android studio나 eclipse를 이용하여 패키징해야 한다는 점... 누가 cmd에서 jar 명령어로 패징한다면 된다고한 글을 보고 줄기차게 따라 하다가 '지정된 경로에 해당 클래스를 찾을 수 없다'는 에러와 3시간 동안 씨름했다. 여튼 플러그인을 jar로 패키징하려면 android studio를 이용하자 (방법은 여기에 자세히 설명됨)
*해당 방법으로 패키징할때 lint에러를 던진다면 여기를 참조하기 바람
구조
대략적인 구조는 위 그림처럼 간단하게 UML 스타일로 도식화해보았다. 노란색 영역이 Plugin에서 구현된 영역이고, 파란색 영역이 Plugin을 활용하는 Unity Script 영역 그리고 초록색 영역이 해당 기능을 Android에서 구현한 부분이다.
대략 해설을 해보면 BluetoothController가 Bluetooth를 이용하여 Android영역에 요청을 날리고, 결과를 BluetoothModel에서 업데이트 받는 방식다. 업데이트를 받았다면 컨트롤러는 옵저버를 상속받기 때문에 Model의 변경 시점을 파악하고, 변경된 데이터를 받아와 처리해서 View를 업데이트할 수 있다. 간단한 구조다.
구현 코드는 대략 완성이 되었는데 Java 메소드를 호출하는 스크립트 부분을 어떤 패턴을 이용할지에 대해 고민을 많이 했다. 이 부분을 싱글톤을 사용하여 해당 java 메소드를 호출하는 유일한 객체로 만들어줄지, 아니면 보다 커플링을 줄이기 위해 유일함을 포기해서 디자인할 것인지. 이것을 MVC 패턴과 어떻게 연결해야 할지에 대한 고민이 대부분이었다.
코드 설명
이 글에서는 모든 소스코드를 설명하지는 않을 것이다. 분량도 분량이지만 안드로이드 블루투스 통신 예제인 'BluetoothChat'을 많이 참고하여 제작할 수 있는 플러그인이고, 공부하는 면에서도 방향만 대략 설명하고 스스로 코드를 읽으면서 이해하는 편이 더 좋을 것으로 생각한다. BluetoothChat에 대한 예제는 오래된 예제라 설명하는 블로그가 많으니 내가 직접 작성한 C#코드를 위주로 설명하려 한다.
위 코드는 두 개의 클래스로 분리되어있다. 블루투스와의 연결을 관리하고 있는 BluetoothService와 이것을 서브 쓰레드로 가지고 있으며 UnityPlayerActivity를 상속받고 있는 BluetoothPlugin이다. 먼저, BluetoothService는 3개의 쓰레드들 가지고 블루투스와의 연결을 관리한다. BluetoothPlugin에서 연결 요청을 보내고 handler를 통해 결과를 받아보게 된다. 통신 결과나 연결 상태, 결과를 상황에 따라 UnityPlayer.UnitySendMessage() 메소드를 이용해 Unity 스크립트로 매핑하여 보낼 수 있게된다.
그럼 이제 어떻게 이 플러그인을 활용했는지 살펴보자. 만들 때 MVC 패턴을 만들도록 유도하여 제작하였기 때문에 Controller와 View정도만 추가로 제작하여 사용하면 될것같다. github에는 좀 더 한눈에 보여주기 위해 Controller와 View의 역할을 합쳐 간단하게 제작하였음을 알린다. 그럼 코드를 살펴보자.
UML처럼 BluetoothModel과 Bluetooth를 가지고 있고, Model로부터 데이터를 받아 Text를 업데이트 하고 있다. Model에서는 Android에서 메세지를 보낼 때마다 업데이트하는 것이 아닌 일정 규격의 패킷이 전송된 것을 감지하면 메시지 큐에 집어넣고, 메시지 큐에 데이터가 업데이트되었다고 알람을 보낸다. 이렇게 하면, 통신 속도에 따라 중간에 데이터가 손실되는 일 없이 안전하게 Bluetooth로 부터 데이터를 전송받고 화면에 표시해 줄 수 있다.
결과
보는 것 처럼 잘 작동합니다. 조이스틱 하나를 트리거(방아쇠)형식으로 사용할 것이기 때문에 특정 방향으로 조이스틱을 당기면 TRIGGER_STATE를 반환할 수 있도록 제작하여 테스한 모습니다.
이 포스팅 이후에 다시 플러그인을 개선시켜 결과물 갤러리에 포스팅 해두었습니다.
여기를 통해 확인 가능합니다.
배포
이번엔 파일이 아니라 Github를 통해 배포합니다. 링크로 들어가서 [Clone or download]를 통해 zip 파일로 다운받아 사용하시면 될것같습니다.