[Unity]Unity mobile native plugin

2022. 4. 12. 23:42Tech/Unity

    목차

이 글은 이전에 운영하던 깃 블로그에서 옮겨온 글입니다.

 

서론

 Unity로 모바일 게임 혹은 앱을 만들다 보면, 모바일 기기가 제공하는 기능들을 사용해야 하는 경우가 있습니다. 혹은 C++로 개발된 라이브러리를 이용해야 하는 경우 또한 있습니다. mobile native 기능 중 일정 시간이 되면 오는 Push notification, 카메라 등이 예시로 들 수 있겠습니다. 일부는 Unity에서 API 등으로 제공하지만, OS별로 차이나 제공하지 않는 기능들은 어떻게 이용해야 할까요? 그냥 안 써야 하나? 아닙니다. 이것을 위해 존재하는 게 Plugin입니다.


Plugin

[그림 1. Unity mobile plugin 구조]

위 그림은 Plugin을 간단하게 그림으로 표현한 것입니다. 위 그림을 요약해 보자면 다음과 같습니다.

Native 기능을 bridge를 이용하여 Unity에 가져오는 것, 이처럼 라이브러리처럼 만든 게 Plugin

 보통 Android와 iOS 개발을 많이 합니다. 각각 Native 앱은 해당 플랫폼에 맞는 언어와 IDE로 개발됩니다. Android는 Android studio로 Java혹은 Kotlin으로 개발을, iOS는 Xcode로 Object- C / Object - C++, Swift를 기본으로 개발을 합니다. Plugin은 각각 언어로 제공되는 Native 기능을 이용하기 위한 API나 구현한 코드를 외부에서 호출하도록 라이브러리 화한 것이라고 할 수 있습니다. 이러한 Plugin을 Native plugin이라고 합니다. 이외에도 Managed plugin이라고 있는데 이는 나중에 알아보도록 하겠습니다. 실제로 Unity공식 매뉴얼에서 이러한 Plugin는 "플랫폼별 고유 코드 라이브러리"라고 정의하고 있습니다.


bridge

 강을 건너 반대편으로 가고 싶다면, 다리(bridge)를 건너야 합니다. Plugin 을 쓰기 위해서도 마찬가지로 입니다. Native로 작성된 코드를 Unity에서는 바로 호출할 수 없기 때문에 C#으로 작성된 다리(bridge)를 호출해서 Native 코드가 Unity 쪽으로 건너올 수 있게 해줘야 합니다.

 


iOS 코드

 iOS코드는. a(Xcode lib),. m(Object-C),. mm(Object-C++),. c(C언어),. cpp(C++ 언어) 파일로 만들 수 있다. 각각 작성한 코드를 Unity 프로젝트의 Assets/Plugins/iOS 폴더에 넣어두면 빌듯이 Xcode에 자동으로 포함됩니다.

// iOS 코드 파일, 예시 .mm 
// Native 코드를 호출할 함수 
(void) PluginFunc() {
	// Native 기능
} 


// .cpp 과 .mm 의 Name Mangling 문제때문에 작성. 
// .c나 .m 일경우 필요 없음. 
// C# Brige 에서 호출할 외부 함수 정의 
extern “C” {      
	void PluginFunc(){ PluginFunc(); } 
}

Native 코드를 작성했으니 bridge가 필요하다. bridge에서는 extern 함수를 호출하는 방식으로 연동해주면 됩니다.

[DllImport (“__Internal”)] 
public static extern void _PluginFunc(); 

// C# 스크립트에서 함수 호출
// iOS 코드에서 정의한 extern 함수
_PluginFunc();

Android 코드

 

Android 코드는. arr(안드로이스 스튜디오 Plugin 아카이브),. jar(Java Plugin 아카이브 )를 만들어서 Unity에서는 Java class를 호출하는 방식으로 연동합니다. iOS와 마찬가지로 각각 작성한 코드를 Unity 프로젝트 Assets/Plugins/Android 폴더에 넣어두면 됩니다. 차이가 있다면 Android는 apk까지 뽑을 수 있기 때문에 AndroidMenifest를 포함해야 합니다. 즉, Android 프로젝트를 위한 모든 설정이 포함되어야 한다는 것입니다. 사실 iOS 보다 접착성은 좋지만 구현이 좀 더 귀찮지 않나 싶습니다.

//Java class 
public class PluginAndroidClass{
	void PluginFunc() { … }
}

 위아같이 class를 작성하여. jar이나. arr 파일로 추출한 후 Assets/Plugins/Android에 넣어 줍니다. 그러고 나서 bridge를 작성하여 해당 class를 호출하면 됩니다.

// C# Brige 
void Func(){
	// UnityPlayer와 연동 되어있으므로 
	AndroidJavaClass pluginClass = new AndroidJavaClass(“Unity패키지명+클래스명”); 
	pluginClass.Call(“PluginFunc”); 
}

실제로 위 과정 외에. jar,. arr로 추출하는 거나 AndroidMenifest 설정이 귀찮았던 것 같습니다.


Native에서 Unity 함수 호출하기

Unity에서는 각각 Native 코드를 호출할 수 있는데 반대로는 어떨까요? 반대도 가능합니다.

 

iOS 코드에서는

void UnitySendMessage(const char* obj, const char* method, const char* msg);​

Android 코드에서는

import com.unity3d.player.UnityPlayer;​ 

public static void UnitySendMessage(String obj, String method, String msg);​

SendMessage와 같은 사용법을 가진다. 예전에 Asset들은 모바일 기기의 Native 기능을 어떻게 가져다 썼는지 궁금했는데, 이와 같이 연동할 수 있다는 사실을 알게 된 후로 궁금증이 가셨던 기억이 납니다.


마무리

여담이지만, 요즘 Unity 에서는 Uaal이라는 구조를 제공합니다. 콘셉트는 Unity프로젝트를 라이브러리화 하여, 별도의 프로젝트에서 이용 가능하게 하자!라는 것인데 자세한 건 나중에 다뤄보겠습니다. 어쨌든, 이 구조를 이용해 보면서 발견하게 된 것이 있습니다. 바로 Swift와 Kotiln 코드도 Plugin으로 만들어서 사용이 가능하다는 것입니다. 사용법은 기존과 비슷하니 참고가 되었으면 합니다.


리소스 출처

[그림 1] : 라인 게임기술개발 블로그, https://m.blog.naver.com/PostView.nhn

 

반응형
LIST

'Tech > Unity' 카테고리의 다른 글

[Unity]직렬화(Serialization)  (0) 2022.04.13
[Unity]로드된 리소스의 메모리 누수  (0) 2022.04.13
[Unity]Scene 사이의 전환  (0) 2022.04.12
[Unity]코루틴(Coroutine)  (0) 2022.04.12
[Unity]Unity Monobehaviour 생명주기(life cycle)  (0) 2022.04.12