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

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
반응형

댓글