파파비의 블로그

Unity ) 유니티에서 C#으로 Android Native Code 실행하기 - (2) C#으로 안드로이드 네이티브 기능 실행해보기 본문

기타

Unity ) 유니티에서 C#으로 Android Native Code 실행하기 - (2) C#으로 안드로이드 네이티브 기능 실행해보기

N. Dave 2020. 10. 9. 20:23
반응형

플러그인을 따로 만들지 않고,

기존에 존재하는 안드로이드 API를 유니티 내의 C# 스크립트를 통해 다뤄보도록 하겠습니다.

 

간단하게 유니티 내에서 Toast 메시지를 띄우는 코드에 대해서 살펴봅시다.

    private void _ShowAndroidToastMessage(string message)
    {
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        AndroidJavaObject unityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

        if (unityActivity != null)
        {
            AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
            unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
            {
                AndroidJavaObject toastObject = toastClass.CallStatic<AndroidJavaObject>("makeText", unityActivity, message, 0);
                toastObject.Call("show");
            }));
        }
    }

유니티도 할줄 알고, C#도 알지만, 이 코드가 이해가 안된다고요?

>> 안드로이드 API를 모르면 그렇습니다. 간단하게 설명해드릴게요

>> 만약 이해하기 싫고, 그냥 toast만 띄우고 싶으면 복사해서 쓰시고, parameter에 원하는 메시지만 넣으면 됩니다.

 

 

안드로이드에서 java를 통해 toast를 띄우는 방식은 다음과 같습니다.

    private void showText(){
        Toast.makeText(this, "보여질 메시지", Toast.LENGTH_LONG).show();
    }

(showText는 제가 만든 메소드이고, 그 안의 한 줄을 살펴보시면 됩니다.)

 

1단계)

Toast class 내에 static 메소드인 makeText 를 통해 필요한 인자들을 넣고 실행하면, toast 라는 객체가 생성됩니다.

 

2단계)

생성된 toast 객체를 .show()를 통해 화면에 보여주게 됩니다.

 

보통은 만들고 보여주기까지 한번에 이뤄지는 경우가 대부분이기에 이렇게 한줄로 쓰지만,

>> 절차는 1) toast를 만들고, 2) 보여주는 2개의 단계로 나누어져 있습니다.

 

 

인자들을 살펴보면

1) this, 2) 메시지, 3) Toast.LENGTH_LONG 이렇게 3개의 인자들이 들어갑니다.

 

1) this

this는 Context 객체를 의미하는데, Activity 객체가 Context를 상속해서 Activity를 넣기도합니다.

Context를 넣는 이유는, 화면 내에서 Toast가 보여질 위치를 알려주는 기능을 한다고 보시면 되는데, 

쉽게 이해하면 "어디 화면 앞에다가 토스트를 띄워줘~" 라고 위치를 말하는 거라고 보시면 됩니다.

만약 이 위치를 이상하게 전달하면 Toast가 다른 화면에 가려져 보이지 않을 수도 있습니다.

(위치라는게 화면 내에 위,아래, 좌우 를 의미하기 보단, 어느 화면 앞에 toast를 위치할 것인가? 의 개념으로 생각하면 됩니다)

 

참고로 안드로이드에서 Activity 는 화면을 의미한다고 간단하게 이해하고 넘어가셔도 됩니다.

 

2) 메시지는 넘어가겠습니다.

 

3) Toast.LENGTH_LONG는 이 TOAST가 얼마동안 보여줘야하는지를 나타냅니다.

Toast.LENGTH_LONG은 사실 int값입니다. 1을 나타내는데, 1은 1초를 의미하는게 아니라,

flag입니다. 실제로는 3.5초 동안 보여지게 됩니다.

Toast.LENGTH_LONG 대신  Toast.LENGTH_SHORT도 있는데 값은 0이며 이는 2초에 해당합니다.

 

 

 

이 과정을 유니티를 통해서는 어떻게 구현되는지 위 코드를 위에서부터 하나씩 살펴보겠습니다.

 

1. context를 가져오는 부분 (toast가 보여질 위치를 알려주는 역할을 하는 인자 구하기)

AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject unityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

- java코드에서 maketoast메소드 안에 첫번째 인자로 "this"를 넣었는데,

거기에 해당하는 값을 가져와야 우리도 넣어줄 수 있겠죠?

그 값을  가져오는 코드입니다.

 

class에 대한 정보를 가져오기 위해선, AndroidJavaClass라는 객체를 사용하며,

class에 대한 정보를 가져올 때는 패키지 + class의 조합을 통해 class 풀네임을 넣어야합니다.

 

이 코드에서는 UnityPlayer라는 class에 대한 정보를 가져왔는데,

UnityPlayer는 Acitivty를 상속한 class로, 이 class를 통해 우린 context 값을 가져올 수 있기 때문입니다.

(참고로 유니티는 UnityPlayer라는 액티비티 클래스를 활용합니다)

 

2번째 줄을 보면 unityPlayer.GetStatic<AndroidJavaObject>("currentActivity") 라는 코드가 실행됩니다.

unityPlayer class 안에, static 메소드인 currentActivity를 실행시키는데, 이 메소드의 return 값은,

AndroidJavaObject다 라는 의미입니다. 유니티에선 java class로 만든 모든 객체는 AndroidJavaObject 객체로 인식합니다. 그리고 객체에 대한 메소드 명은 Call 메소드를 통해 첫번째 인자에 string 값으로 전달하며, 인자들은 그 뒤에 순서대로 넣어주면 됩니다. return 값의 type을 <>를 통해 명시해줬는데, 실제로 return 값이 void가 아닌 이상 저 꺽쇠를 통해 명시를 안한다면 유니티는 메소드를 찾지 못해 에러가 납니다.

 

 

2. 필요한 내용 넣고, Toast 보여주도록 실행하기

if (unityActivity != null)
        {
            AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
            unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
            {
                AndroidJavaObject toastObject = toastClass.CallStatic<AndroidJavaObject>("makeText", unityActivity, message, 0);
                toastObject.Call("show");
            }));
        }

이제 context 부분까지 구했으니 필요한 인자 3개는 다 있게 됐습니다.

(인자 3개는 context, 메시지, 시간인데 , 메시지랑 시간은 그냥 입력하면 되니까!)

 

아까 java 코드에서는 Toast.makeText() ~ 를 통해 접근했는데, 이게 Toast 라는 class를 통해 makeText라는 static 메소드를 실행했고, 이 것의 return 값은 Toast 객체라고 했습니다.

 

그래서 여기서도

AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");

를 통해 Toast class에 대한 정보를 객체로 가져왔고, 

 

 AndroidJavaObject toastObject = 
 toastClass.CallStatic<AndroidJavaObject>("makeText", unityActivity, message, 0);
 toastObject.Call("show");

내부적으로 toastObject를 만들어서, AndroidJavaObject로 받은 뒤에, show메소드를 .Call를 통해 호출하는 것을 볼 수 있습니다. 꺽쇠가 없는 것을 보니 show 메소드는 return 값이 없나봅니다.

 

또한 toastObject를 만들 때, 맨 앞에 메소드 이름이 string 값으로 전달되고, 그 뒤에 그 메소드에 대한 인자 3개가

들어가는 것을 볼 수 있습니다. unityAcitivity는 아까 우리가 구한 context값이며, 그 뒤에 메시지, 그리고 마지막으로

0이라는 toast 길이에 대한 값을 전달합니다 .

 

 

 

 

 

 

그런데,

 

 

unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>

이 부분에 대해선 생략하고 넘어가려고 합니다.

쓰레드와 관련된 부분인데 또 다른 영역이라서 내용이 많습니다.

이 쓰레드에 관련해서는 다루게 되면 유니티 관련 글이기라기 보다

안드로이드 관련 글이 되어 나중에 안드로이드 글을 쓸 때 다뤄보도록 하겠습니다.

 

 

반응형
Comments