본문 바로가기
공허의 유산/표현의 자유

Unity3d에서 AAR 사용하기 실습

by 바른생활머시마 2023. 3. 5.
728x90

애초의 목표는 Android 앱에 Unity3d 뷰를 embedding 하는 것이었는데, 이걸 하려면 기본적으로 aar과 unity와의 관계에 대한 공부가 필요한 것 같습니다. Unity3d에서 직접 apk를 만들 수도 있지만, 좀 더 세부적인 설정을 변경하여 빌드하기 위해 프로젝트를 export하여 Android Studio에서 프로젝트를 빌드 할 수도 있습니다.

 

 아무튼, 이런 관계들 중에서 사용 할 수 있는 것이 무엇인지 확인을 해둬야 필요할 때 사용 할 수 있는 기술이 무엇인지 판단하고 개발 방향을 정할 수 있기 때문에 무엇이든 한번 알아보기로 했습니다.

 

여러가지 자료를 찾아보고 시도 해 봤는데, 결코 쉽지 않았습니다.

Android Studio나 Unity3d의 프로젝트 설정이나 빌드 설정을 할 일이 그다지 없어 작은 문제가 생기면 어느 부분에서 발생하는지 알 수가 없었습니다. KeyStore까지 해줘야 하는지 결코 몰랐죠.

 

 

그렇게 여러 자료를 보고 시도하다가 좌절하고, 다시 해보자며 영어로 된 유튜브 자료 봐 두었던 것을 보려고 하다가, 거의 비슷한 내용이 한글로 되어 있는 것을 보고 한번 따라 가 보기로 했습니다.

 

참고 프로젝트

 

참고한 동영상은 아래 채널입니다. 4년 전에 올리신 영상인데 지금은 훨씬 더 전문가의 포스를 풍기고 좋은 영상을 많이 올리고 계신 것 같네요.

https://www.youtube.com/@nkstudio9161

 

NK Studio의 유니티 스페셜 테크닉

국내 유니티를 사용한 코딩 유튜브 체널! 회사 업계에서 사용할만한 기술도 소개합니다

www.youtube.com

 

참고했던 영상은 아래 영상입니다. 본 영상을 직접 보면서 따라 해 보는 것도 좋을 것 같아요.

https://www.youtube.com/watch?v=B7a6xpMXDYE 

 아래는 영어로 된 것인데, 재생목록이나 내용이 거의 비슷하네요. Context 대신 Activity를 사용하신 것을 보면, 나름 최신 환경에서 업데이트 하시면서 쓰신 것 같아요. . NK Studio에는 4년 전에 올라왔고, 아래는 1년 전이니까 한국분 것이 오리지널인 것 같습니다.  훌륭하십니다.

https://www.youtube.com/watch?v=6u7FV-e6nUc&list=PLgdJs67VIHij7g5vf-AYChkSNn8X73ECS 

 

AAR 생성 

Android Studio에서 AAR을 생성 해 보겠습니다. 앞에서 AAR 만들어 사용하는 글을 썼는데, 굳이 Empty Activity 템플릿 프로젝트를 만들 필요가 없이 그냥 No Activity로 했어도 되었네요. 이것저것 많이 배웁니다.

 

프로젝트 생성

 

New project / No Activity

 

 

프로젝트 이름을 정하고, 이 때 Minimum SDK 버젼은 좀 신경을 써야 합니다. 실제로 혼자서 영어 버젼 보면서 할 때 이 버젼 문제 때문에 안되는 것인가 싶었는데, 정말 중요한 부분인 것이 맞네요. 영어 영상에는 이런 자세한 설명이 나오지 않는데, 원본 영상에는 도움이 되는 말씀을 많이 해주시는 것 같습니다.

 

Module 생성

아래 순서에 따라 모듈을 만듭니다.

app / New / Module

요런 방법도 된다는 것도 겸사 겸사 배웠습니다. 

AAR 설정창에서 Package name은 나중에 Unity에서 불러올 때 사용하는 것이니 잘 작성 해 줍니다. 

그리고, 저기 Minimum SDK 잘 챙겨야 합니다.

 

영어 영상에서는 없었던 내용인데, 아래와 같이 불필요한 내용을 지우라는 말씀도 해주셔서 좋았습니다.

Module 확인 후 androidTest/ test는 삭제

 

그리고 AAR의 실제 내용이 될 라이브러리를 JAVA Class로 구현하기 위해 JAVA Class를 하나 추가합니다.

처음에 이런 공부를 할 때는, 이게 원래 지정 된 문구인지, 내가 설정한 값에 의해서 결정 된 것인지 잘 구분이 안되는 경우가 많습니다. 그래서, 일부러 클래스 이름에 Class라고 적어서 잘 구별 되도록 해 두고 진행하였습니다.

 

 

Class 내용은 아래와 같습니다. 

Instance를 Singleton 으로 만들었습니다. 영상에서는 함수를 private로 하셨는데, 저는 외부에서 호출하는 것이라 public으로 하는 것이 맞을 것 같아서 public으로 했어요. private으로 해도 되는지는 확인 해 보지 않았습니다. 코드 자체가 복잡하지는 않고,  singleton 구현 내용과 토스트 띄우는 내용이 거의 대부분 입니다.

package com.red.unitypluginaddtoast;

import android.content.Context;
import android.widget.Toast;

public class UnityPluginAARClass {

    // Instance
    private static UnityPluginAARClass m_instance;
    public static UnityPluginAARClass instance() {
        if(m_instance == null) {
            m_instance = new UnityPluginAARClass();
        }
        return m_instance;
    }

    // Context
    private Context context;
    public  void setContext(Context ct) {
        context = ct;
    }
    public void ShowToast(String msg, int length) {

        if( length == 0) {
            Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
        }
        else {
            Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
        }

    }
}

 

이제 코드가 준비되었으니, 빌드를 하여 AAR 파일을 만듭니다.

요렇게 만들어진 AAR을 Unity에서 사용하게 됩니다.

 

 

 

 

Unity

 

Unity 프로젝트는 영어 영상 보면서 하다가 잘 안되서 좌절하고 있던 중이었어요. 그 프로젝트 기반에 새 AAR을 추가하고, 새 Script를 추가하여 준비했습니다.

 아래와 같이 Plugins 폴더와 그 하위에 Android 폴더를 만들어 AAR 파일을 넣습니다. 이 때 폴더 이름을 꼭 저렇게 해야하는지도 사실 좀 궁금한데 확인 해 보지는 않았습니다. 영문 영상을 따라 하느라 좀 지쳐서..ㅋㅋ

 

AAR 파일을 추가하고~

새로운 스크립트 파일도 추가합니다.

 

스크립트 내용은 아래와 같습니다. 

그런데, 영어 영상과 내용이 좀 달라요. 이 부분은 영상 내용을 참고 하시는 것이 큰 도움이 될 것 같습니다.

이 부분에 특히나 항상 같은 내용으로 써야 할 것과 내가 입력한(Android에서...) 내용에 따라서 결정되는 것이 섞여 있어서 관련 된 내용을 들으면 도움이 될 것 입니다.

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

public class AndroidPlugin : MonoBehaviour
{
    //Android Java Objects
    private AndroidJavaObject UnityActivity;
    private AndroidJavaObject UnityInstance;


    // Start is called before the first frame update
    void Start()
    {
        //Instantiation
        AndroidJavaClass ajc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        UnityActivity = ajc.GetStatic<AndroidJavaObject>("currentActivity");

        AndroidJavaClass ajc2 = new AndroidJavaClass("com.red.unitypluginaddtoast.UnityPluginAARClass");
        UnityInstance = ajc2.CallStatic<AndroidJavaObject>("instance");

        UnityInstance.Call("setContext", UnityActivity);


    }

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

    public void ToastButton()
    {
        ShowToast("Call from Unity", false);
    }

    public void ShowToast(string msg, bool isLong)
    {
        UnityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
        {
            if (isLong == false)
            {
                UnityInstance.Call("ShowToast", msg, 0);
            }
            else
            {
                UnityInstance.Call("ShowToast", msg, 1);
            }

        }));
    }
}
반응형

 

Unity에서도 min SDK version을 잘 맞춰줘야 합니다.

Project Setting / Player / Other / Identification에 Minimum API Level이 있습니다. 이것을 AAR에 있던 것과 같게 해줍니다.

(만약, 상용 라이브러리를 쓰려면 어떻게 맞춰 줄 수 있을지 좀 궁금해지네요.)

 

이것이 맞지 않으면, 아래와 같은 오류가 날 수도 있습니다.

 

 

 

빌드 & 실행

 

 기대를 안고 빌드를 했는데, Key Store 문제로 생겼던 문제가 또 생겼습니다. 급 좌절....

 일단 새로운 Key Store를 만들어서 했는데도 뭐가 또 안되고...

 전에 못봤던 아래 경고창이 뜨기에 가만히 읽어보니, IL2CPP와 ARM64를 적용해야 하는 것 같네요.

요렇게 설정하고 빌드를 하니까, 하~~~~~~~~~~~~안참을 빌드를 했습니다.

희망적인 현상이죠~

 

 

 

결과는 아래와 같이 버튼을 누르면 아래쪽에 토스트가 발생하는 것을 볼 수 있습니다.

이 코드를 기본 틀로 잡아서 여러가지 응용과 확장을 해 나가보면 좋을 것 같습니다.

 

 

시간 정보에서 분과 초를 더하여 화면에 출력하는 샘플도 한번 해봤습니다. Toast를 띄울 때는 runOnUiThread를 사용했어야 했는데 이렇게 간단한 함수를 직접 호출해도 문제가 없는 것 같습니다. 그런데, 자칫 잘못하면 ANR을 띄울 가능성이 있으니 주의 해야 될 것 같아요.

    public void onClickAdd()
    {

        Debug.Log("Button is pressed.");
        int minutes = System.DateTime.Now.Minute;
        int seconds = System.DateTime.Now.Second;
        int sum = minutes + seconds;

        if (utilClassInstance != null)
        {
            sum = utilClassInstance.Call<int>("AddInt", minutes, seconds);
            string result = string.Format("{0} + {1} = {2}", minutes, seconds, sum);
            Debug.Log(result);
            resultText.text = result;
        }
        else
        {
            Debug.Log("Instance is null");
            resultText.text = "Initance is null";
        }

    }

결과는, (동영상 크기 조정 하는 방법을 좀 알아봐야 될 듯 하네요.)

 

 

 

위 내용은 Android에서 구현한 라이브러리를 Unity3d에서 사용한 경우인데, 그 반대의 경우처럼, Unity3d의 Game화면을 Android에 넣고 상호 Interfacing 하는 방법도 알아가야겠습니다.

728x90
반응형

댓글