Unity3D Android Plugin 이클립스에서 빌드하기

 아래 내용은 유니티3D 버전에 따라 lib, bin 폴더 내용도 좀 달라지고 또한 공식 지원 방식이 아니니 Unity3D Prime31 처럼 자신만의 안드로이드 플러그인을 만들어보자 포스팅을 참고하시기 바랍니다.

 지난번에 유니티3D에 안드로이드 jar 플러그인 만드는 것을 정리했었습니다. 이클립스에서 안드로이드 프로젝트를 lib 프로젝트로해서 jar로 추출 후 유니티3D에서 가져다 사용하는 것이었죠.

 이번엔 반대로 유니티에서 빌드한 안드로이드 프로젝트를 이클립스에서 가져다가 연동해 빌드하는 것을 정리해봅니다. 즉 유니티3D 을이되어 빌드한 안드로이드 프로젝트가 플러그인 역활을 하고 이클립스가 갑이 되는거죠. 유니티3D에서 안드로이드 빌드 자동으로 해주는데 왜 이클립스에서 따로 빌드를 하지? 하며 의아해하실분도 있을 듯합니다. 나중에 2가지 방식의 차이점이나 장단점을 따로 정리해보겠습니다.

 이클립스 설치 같은 기초 준비 내용은 링크를 참고하시기 바랍니다.


1. 이클립스 안드로이드 프로젝트 생성

 이클립스 안드로이드 프로젝트 만들기를 참고하셔서 메인으로 사용할 안드로이드 프로젝트를 만듭니다. 전 이름은 EclipseBuildUnity3D, 패키지명은 com.wwforever.eclipsebuildunity3d 했습니다.

 기존 Jar를 유니티에서 가져다 사용하는 것과 다르게 이번에는 Mark this project as a library는 체크 해제하고 만들어야합니다. 위에서도 언급했듯이 이제는 이클립스가 갑이기 때문이죠.


2. 유니티3D 프로젝트 생성 및 빌드

 유니티3D 프로젝트를 만드시고 Build Settings에서 Android의 Bundle Identifier를 위에서 만들었던것과 같게 com.wwforever.eclipsebuildunity3d 로 세팅해줬습니다. 그리고 Build를 해서 임시 안드로이드 프로젝트를 생성합니다. 생성된 apk는 무시합니다. 제가 만든 유니티3D 프로젝트는 Unity3DEclipseBuild 입니다.


3. 유니티3D에서 빌드한 임시 안드로이드 프로젝트 이클립스로 가져오기

 유니티3D에서 빌드 된 임시 안드로이드 프로젝트는 프로젝트 디렉터리/Temp/StagingArea 에 생깁니다. 이 디렉터리를 다른 곳에 복사해줍니다. 저는 위와같이 유니티3D와 이클립스 프로젝트 디렉터리와 같은 위치에 복사시켰습니다. 일단은 한번만 이렇게 디렉터리를 통으로 복사해주면 됩니다.

 이클립스에서 File -> Import를 하시는데 위와같이 Existing Android Code Into Workspace를 해줍니다. 저는 지금것 다른 안드로이드 프로젝트를 임포트할 때 Existing Projects into Workspace로 했었는데 유니티3D에서 만들어진 안드로이드 프로젝트는 밑에껄로 해줘야하네요.

 복사했던 StagingArea 디렉터리를 가져오기합니다.


4. 프로젝트 속성 수정 및 Lib 추가

 먼저 임포트한 유니티 안드로이드 프로젝트인 UnityPlayerProxyActivity를 lib 프로젝트로 하기위해 스샷과 같이 Is Library를 체크해줍니다.

 그리고 메인 안드로이드 프로젝트에서는 UnityPlayerProxyActivity를 스샷과 같이 Library로 추가를 해줍니다.

The container 'Android Dependencies' references non existing library 'D:\ProgramSource\EclipseBuildTest\Unity3DEclipseBuild\Temp\StagingArea\bin\unityplayerproxyactivity.jar' EclipseBuildUnity3D

 위와 같은 에러가 발생할 수 있는데 UnityPlayerProxyActivity를 빌드해주면 해결됩니다.

 마지막으로 안드로이드 플러그인 연동에 필요한 classes.jar 파일을 Java Build Path에서 Add External JARs로 추가합니다. 맥과 윈도우에 따라 classes.jar 파일의 위치가 다른데 링크를 참고하시기 바랍니다.

 그리고 Caused by: java.lang.ClassNotFoundException: .MainActivity 에러를 대비해서 Order and Export에서 classes.jar를 체크해줍니다.


5. assets 복사


 이클립스에서 유니티3D를 빌드할 때는 libmono.so 등이 필요합니다. 링크를 참고하시어 UnityPlayerProxyActivity의 assets안에 있는 bin, libs 디렉터리를 안드로이드 메인 프로젝트의 assets에 복사합니다.


6. MainActivity 수정

package com.wwforever.eclipsebuildunity3d;

import android.os.Bundle;

import com.unity3d.player.UnityPlayerActivity;

public class MainActivity extends UnityPlayerActivity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  //setContentView(R.layout.activity_main);
 }
/*
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }
*/
}
 필요없는 setContentView와 onCreateOptionsMenu 함수를 삭제합니다.


7. 빌드 및 실행

 이제 빌드 후 실행해보면 유니티3D splash.png 의 이미지가 지나간 후 위와 같이 실행된 것을 확인할 수 있습니다.


8. 유니티3D 프로젝트 변동사항 적용하기

 위 환경에서 간단하게 안드로이드와 유니티 통신하는 부분을 추가해보겠습니다. 이는 유티니3D에서 변경이 있을때에 대한 처리를 정리하기 위함입니다.


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

public class PluginEclipseManager : MonoBehaviour 
{
 static PluginEclipseManager _instance;
 private AndroidJavaObject curActivity;
 public string strLog = "Unity3D Android Eclipse Build Sample";
 public static PluginEclipseManager GetInstance()
 {
  if( _instance == null )
  {
   _instance = new GameObject("PluginEclipseManager").AddComponent();    
  }
  
  return _instance;
 }
  
 void Awake()
 {
  AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
  curActivity = jc.GetStatic("currentActivity");
 }

 public void JNICall(string strMsg)
 {
  curActivity.Call("JNICall_U", strMsg);
 }
 
 void JNICall_J(string strMsg)
 {
  SetLog(strMsg);
 }

 protected void SetLog(string strLog)
 {
  this.strLog = strLog;
 }
}
 유니티3D에서 사용하는 싱글턴 컴포넌트를 간략화한 PluginEclipseManager 컴포넌트입니다. 간단하게 안드로이드와 통신하기 위해 JNI 처리를 하고 있습니다. 이런 부분들은 기존에 유니티3D가 갑이었던 부분과 다르지 않습니다.


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 fYpos = 0;
  GUI.Label(new Rect(0, fYpos, 400, 100), PluginEclipseManager.GetInstance().strLog);
  
  fYpos += 50;
  if (GUI.Button (new Rect(0, fYpos, 100, 50), "JNI Call") == true)
  {
   PluginEclipseManager.GetInstance().JNICall("HelloWorld");
  }
 }
}

TestGUI 컴포넌트입니다. 간단히 버튼을 만들고 로그를 출력합니다.


package com.wwforever.eclipsebuildunity3d;

import android.os.Bundle;

import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;

public class MainActivity extends UnityPlayerActivity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  //setContentView(R.layout.activity_main);
 }
/*
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
 }
*/
 public void JNICall_U(String strMsg) {
  String strSendMsg = strMsg + " Success Unity3D Eclipse Build";
  UnityPlayer.UnitySendMessage("PluginEclipseManager", "JNICall_J", strSendMsg);
 }
}
 마지막으로 안드로이드 처리부분입니다. 유니티로부터 온 JNI 메세지를 받아 바로 스트링을 추가한 후 유니티3D에 바로 보내주는 간단한 기능입니다.

 TempGUI.cs를 Main Camera에 붙이시고 유니티3D를 빌드합니다. 역시나 생성된 apk는 무시하고 위 스샷과 같이 유니티3D프로젝트의 Temp/StagingArea/assets/bin 디렉터리만 안드로이드 프로젝트의 assets에 복사합니다. libs는 처음에만 필요합니다. 이렇게 유니티3D 변동사항이 있을때마다 StagingArea/assets/bin 디렉터리를 복사하시면 됩니다.

 적용된 모습입니다.

 지금까지 유니티3D에서 만들어진 안드로이드 임시 프로젝트를 이클립스에서 가져와 빌드하는 것을 정리해봤습니다. 다음에 시간날 때 위에서 언급한 안드로이드 플러그인 2가지 방식에 대한 차이점을 정리해보겠습니다.

이 블로그의 인기 게시물

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

CMake Windows에 설치하기

Unity3D iOS Plugin 만들어 연동하기