Unity3D Prime31 처럼 자신만의 안드로이드 플러그인을 만들어보자

 유명한 프라임31까지 언급하고 제목이 좀 거창하네요. 이미 유니티3D에서 최종 빌드하는 플러그인 작업과 이클립스에서 최종 빌드하는 플러그인 작업을 정리했었습니다. 2가지가 있는데 왠 플러그인 작업이 더 있겠는가 싶겠지만 유니티3D 4.x 부터 지원하기 시작하는 Google Android Project 기능을 가지고 정리를 해볼려고합니다.

 아래 내용을 보시면 아시겠지만 결과적으로는 이미 정리했던 2가지 방식을 적절히 혼합한 하이브리드 방식이라고 생각이 됩니다. 또한 수많은 플러그인 작업을 해오면서 여러 이슈를 해결해오다보니 개인적으로 지금 정리하는 3번째 플러그인 방식을 추천 드립니다.

 왜 추천드리는지 3번째 플러그인 방식의 장점과 단점을 나열해보자면,

  • 장점
    1. setContentView, app_icon 등 초기 AndroidManifest.xml 수정 이슈가 없다.(서드파티 SDK를 붙인다면 수정할 수 있다)
    2. 임시 이클립스 프로젝트인 Temp/StagingArea와 하위에 있는 assets/bin과 assets/libs를 복사할 필요가 없다.
    3. MainActivity와 의존성이 없다(사실 이건 기존 방식으로도 가능)
    4. 중국 바이두 MobAds 광고 SDK는 이 방식으로 작업을 해야 했다.(2번째 방식도 가능)
    5. 결과적으로 경험상 여러 플러그인 작업과 관련된 이슈가 더 적다.
  • 단점
    1. 유니티3D에서 바로 빌드&실행이 안되고 iOS 빌드와 같이 한단계 거쳐 이클립스에서 빌드 한다.
 사실 프라임31의 플러그인들이 어떻게 구성되어 있는지는 한번도 보지 않아서 모르겠습니다. 아마 이제 정리하는 방식 같지 않을까 추측해봅니다. 그럼 유니티3D 안드로이드 플러그인 최종판?에 대한 것을 정리해봤습니다.

1. 이클립스 안드로이드 프로젝트 익스포트

 먼저 유니티3D 프로젝트를 아래와 같이 만들었습니다.



 안드로이드 이클립스 프로젝트를 만들기 위해 Build Settings에서 Android - Google Android Project에 체크를 해주시고 Export 진행합니다.



 Product Name인 Unity3dAndroidBuild가 Export한 이클립스 안드로이드 프로젝트이고 밑에 Unity3dProject는 유니티3D 프로젝트입니다.



 프로젝트를 가져오기 위해 이클립스 실행 후 Import - Android - Existing Android Code Into Workspace 로 선택합니다.



 Browse를 눌러 조금전에 유니티3D에서 Export한 이클립스 프로젝트를 선택 후 Finish를 클릭합니다.



 아래는 임포트 한 직후의 스샷입니다. 2번째 플러그인 방식으로 따로 복사해줬던 bin과 libs가 이미 포함되어 있습니다. libs는 기존에 assets에 복사해줬는데 이제는 알아서 libs 안으로 제 위치를 찾아갔네요.



 이 상태에서 빌드하고 실행하면 아래와 같이 기본적인 실행 모습을 볼 수 있습니다. 처음에도 언급했듯이 setContentView나 app_icon 수정 이슈가 없습니다.

 참고로 지금은 샘플이라 불필요하지만 나중에는 서드파티 SDK를 연동하게 된다면 AndroidManifest.xml를 Assets\Plugins\Android 에 복사해주고 내용을 수정해줘야 합니다.



2. UnityPlayerNativeActivity에서 유니티3D C#과 연동하기

 유니티4.3 에서는 Minimum API 가 2.3.1 즉 API 9부터 있더군요. 그래서 생성된 Activity도 NativeActivity를 상속하는 UnityPlayerNativeActivity입니다. 이제 안드로이드 자바와 유니티3D C# 연동을 정리해봅니다.

 2가지 방식이 있는데 간단하게 자동으로 생성된 UnityPlayerNativeActivity.java 파일을 수정하는 것과 플러그인 프로젝트를 따로 만들고 jar 파일로 익스포트해서 사용하는 방법입니다. 먼저 간단한 첫번째 방식입니다. 예전에 정리했던 방식과 소스코드는 크게 다를건 없습니다.


public class UnityPlayerNativeActivity extends NativeActivity
{
...
// 유니티3D에서 호출하는 함수
public void CallAndroid_U(String strMsg)
{
String strSendMsg = strMsg + " Hello Unity3D";
UnityPlayer.UnitySendMessage("AndroidPluginManager", "SetLog", strSendMsg);
}
}


//AndroidPluginManager.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class AndroidPluginManager : MonoBehaviour
{
static AndroidPluginManager _instance;
private AndroidJavaObject curActivity;
private AndroidJavaClass firstPluginJc;

public string strLog = "Westwood Forever Unity3D Android Plugin Sample";

public static AndroidPluginManager GetInstance()
{
if( _instance == null )
{
_instance = new GameObject("AndroidPluginManager").AddComponent<AndroidPluginManager>();
}

return _instance;
}

void Awake()
{
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
curActivity = jc.GetStatic<AndroidJavaObject>("currentActivity");
}

public void CallAndroid(string strMsg)
{
//자바 호출
curActivity.Call("CallAndroid_U", strMsg);
}

protected void SetLog(string strLog)
{
this.strLog = strLog;
}
}


//TestGUI.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class TestGUI : MonoBehaviour
{
// Update is called once per frame
void Update ()
{
if (Application.platform == RuntimePlatform.Android)
        {

            if (Input.GetKey(KeyCode.Escape))
            {
                Application.Quit();
                return;
            }
}
}

void OnGUI()
{
float fXpos = 0;
float fYpos = 0;
GUI.Label(new Rect(fXpos, fYpos, 400, 100), AndroidPluginManager.GetInstance().strLog);

fYpos += 50;
if (GUI.Button (new Rect(fXpos, fYpos, 100, 50), "CallAndroid") == true)
{
AndroidPluginManager.GetInstance().CallAndroid("Hello Java");
}
}
}

 이제 Main Camera에 TestGUI를 붙여주고 처음에 했던대로 빌드 세팅에서 Google Android Project 체크된 상태로 이클립스 프로젝트를 같은 폴더에 익스포트합니다.

Description Resource Path Location Type
File is Out of sync AndroidManifest.xml /UnityPlayerNativeActivity line 1 Android ADT Problem

 이클립스에서 바로 빌드하면 위와 같은 에러가 발생할 수 있는데 F5 키를 눌러서 갱신을 해주고 빌드 후 실행하면 아래와 같은 결과를 볼 수 있습니다.



3. 안드로이드 JAR 플러그인 프로젝트 만들어 연동

 마지막으로 유니티3D에서 익스포트해 자동 생성된 java 파일은 건들지 않고 따로 안드로이드 jar 플러그인 프로젝트를 만들어서 적용을 해보겠습니다. 일단 위에서 작업했던 UnityPlayerNativeActivity의 CallAndroid_U 삭제합니다.

 Unity3dAndroidTestPlugin이라는 안드로이드 JAR lib 프로젝트 를 아래와 같이 만들었습니다.




 이제 방금 만든 Unity3dAndroidTestPlugin과 유니티에서 익스포트했던 UnityPlayerNativeActivity 프로젝트가 있습니다.



 JAR 파일로 만들기 전에 간단한 기능을 하는 Class를 아래와 같이 만들어줍니다. 저는 이름을 FirstAndroidPlugin 이라고 했습니다.




package com.westwoodforever.unity3dandroidtestplugin;

import com.unity3d.player.UnityPlayer;

public class FirstAndroidPlugin {
public static void CallAndroid_U(String strMsg)
{
String strSendMsg = strMsg + " Hello Unity3D";
UnityPlayer.UnitySendMessage("AndroidPluginManager", "SetLog", strSendMsg);
}

}

 기능은 간단합니다. 기존에 UnityPlayerNativeActivity.java에서 처리했던 코드를 직접 가져왔습니다. 소스코드에 UnityPlayer.UnitySendMessage가 쓰이고 있으니 import com.unity3d.player.UnityPlayer 를 해줘야하고 이것을 프로젝트에서 알 수 있게 아래와 같이 Properties - Java Build Path에 유니티의 classes.jar를 추가합니다.



 프로젝트를 빌드 후 jar 플러그인을 만들기 위해 마우스 우클릭 - Export - Java - JAR file 을 선택합니다.



 익스포스시 필요한 파일은 src만 있으면 됩니다 나머지는 체크 해제합니다. 경로와 이름을 지정 후 Finish를 누르면 됩니다. 저는 바로 유니티3D 프로젝트의 Plugins\Android 폴더에 FirstAndroidPlugin.jar로 익스포트 해줬습니다.



 유니티3D를 보면 아래와 같이 갱신이 된 것을 볼 수 있습니다. 이렇게하면 다음 Google Android Project로 익스포트할 때 UnityPlayerNativeActivity 프로젝트에 자동으로 jar 플러그인이 libs에 포함됩니다.



// AndroidPluginManager.cs

// Add
private AndroidJavaClass firstPluginJc;


void Awake()
{
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
curActivity = jc.GetStatic<AndroidJavaObject>("currentActivity");
// Add
firstPluginJc = new AndroidJavaClass("com.westwoodforever.unity3dandroidtestplugin.FirstAndroidPlugin");
}

public void CallAndroid(string strMsg)
{
//curActivity.Call("CallAndroid_U", strMsg);
firstPluginJc.CallStatic("CallAndroid_U", strMsg);
}

 유니티3D 프로젝트를 Google Android Project로 최종 익스포트 하기전 위와 같이 소스를 약간 수정합니다. 기존에 UnityPlayer 안드로이드 자바 클래스의 currentActivity를 가져왔다면 이번에는 직접 만든 플러그인의 자바 클래스를 가져오게 했습니다. 자바 함수 호출도 curActivity가 아닌 만든 플러그인에 있는 static 함수를 호출해줍니다.

 이제 Google Android Project로 익스포트 후 이클립스에서는 갱신을 한번 한 후 빌드 후 실행하면 아까와 같은 결과를 볼 수 있습니다.


 이렇게 안드로이드 자바쪽 플러그인 소스가 수정이 되면 jar 파일 익스포트하고 유니티3D에서 Google Android Project 익스포트를 계속 반복하면서 작업을 진행하면 됩니다. 플러그인 하나에 모든 기능을 다 넣으셔도 되고 각각 jar 프로젝트로 만들어서 작업을 하시면 됩니다.

이 블로그의 인기 게시물

CMake Windows에 설치하기

Unity3D iOS Plugin 만들어 연동하기