Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Game Development with Unity from an Android Point of View @DevFestNantes

Game Development with Unity from an Android Point of View @DevFestNantes

Developing mobile games with Unity has become more and more popular these years, and Unity developers often need to tackle OS specific challenges.

Through this talk you will discover how to work with Unity as an Android Developer. You will see how to build Unity plugins using the JNI and Java/Kotlin, which is the most efficient way to link Unity with the Android framework.

Every Unity project can be exported as an Android Studio project with a Gradle support. You'll also see how you can integrate Unity inside a native Android Java/Kotlin application, or how to get a full control of the build process so you can benefit from the best of both worlds.

Julien Salvi

October 22, 2019

More Decks by Julien Salvi

Other Decks in Programming


  1. Game Development with Unity from an Android Point of View

    Place your screenshot here Julien Salvi
  2. Android addict since Froyo Punk rock & IPA! You can

    find me at @JulienSalvi Julien Salvi Senior Android Engineer @ Innovorder
  3. × Game Development on Android × Building Unity Plugins ×

    Unity from Android Studio × What’s next?
  4. × Available on Windows and Mac (soon on Linux) ×

    2D, 3D games or AR/VR apps × Fast prototyping, fast scripting × Supporting most of the 3D and 2D formats Great Asset Store! Game development on Android Building Android apps with Unity
  5. × OpenGL and Vulkan support × Bridge to native platforms

    × Android Studio project export × Java and Kotlin support Game development on Android Building Android apps with Unity
  6. Building Unity plugins Game Developers with Unity × Build apps

    with C# scripts × Control the rendering pipeline × Cross-platform shader compilation Bring the best experience at a high frame rate!
  7. × Build your plugin using Java/Kotlin or C/C++ × Android

    plugins might be: .jar, .aar or .so × Add Java or Kotlin classes directly into your Unity Project Build an Android Plugin for Unity
  8. Android Plugin for Unity For example let us build a

    player plugin for Unity Call player methods from Unity
  9. public class PlayerBridge { private Context ctx; public PlayerBridge(Context ctx)

    {} public void addSubtitles(String path) {} public void doOnMainThread(boolean playWhenReady) {} public int getTrackCount() {} } Android Plugin for Unity
  10. Calling a JAVA/Kotlin object from Unity AndroidJavaObject localMediaPlayer = null;

    using (AndroidJavaClass javaUnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { using (currentActivity = javaUnityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) { localMediaPlayer = new AndroidJavaObject("my/plugin/vr/PlayerBridge", currentActivity); if (localMediaPlayer != null) { // Do some work with your java object outside the Android UI thread localMediaPlayer.Call("addSubtitles", subtitleURL); int count = localMediaPlayer.Call<int>("getTrackCount"); currentActivity.Call("runOnUiThread", new AndroidJavaRunnable(() => { // Do some work on Android UI thread localMediaPlayer.Call("doOnMainThread", true); })); } } }
  11. Function inside your plugin Define the plugin function in your

    Unity script extern "C" { float FooPluginFunction (); } C/C++ Plugin [DllImport ("PluginName")] private static extern float FooPluginFunction ();
  12. Better performances when you call your Java plugin through the

    JNI Important: JVM loading jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* jni_env = 0; vm->AttachCurrentThread(&jni_env, 0); return JNI_VERSION_1_6; } Java and C/C++ Plugin
  13. JNI method for calling a method in a Java class

    JNIEXPORT jobject JNICALL Java_com_example_NativeClass_nativeMethod(JNIEnv* env) { jclass cls_JavaClass = env->FindClass("com/your/java/Class"); // find class definition jmethodID mid_JavaClass = env->GetMethodID (cls_JavaClass, "<init>", "()V"); // find constructor method jobject obj_JavaClass = env->NewObject(cls_JavaClass, mid_JavaClass); // create object instance return env->NewGlobalRef(obj_JavaClass); // return object with a global reference } Java and C/C++ Plugin
  14. static void UNITY_INTERFACE_API OnRenderEvent(int eventID) { switch((GLEvent)eventID) { case Initialize

    : InitMediaSurface(); break; case Shutdown : mediaSurface->Shutdown(); mediaSurface = NULL; break; case Update: mediaSurface->Update(); break; case Resize: mediaSurface->ResizeTexture(); break; } } Java and C/C++ Plugin static void UNITY_INTERFACE_API OnRenderEvent(int eventID); enum GLEvent { Initialize = 0, Shutdown = 1, Update = 2, Resize = 3 }; Sending event to the native surface for low-level rendering
  15. Set a native callback and dispatch an event to the

    native plugin from Unity // Set the native callback from Unity _inptr_native_callback_delegate = Marshal.GetFunctionPointerForDelegate(NativeCallback); // Native method from the plugin CINEVR_AndroidNative_SetNativeCallback(_inptr_native_callback_delegate); Java and C/C++ Plugin // Get native callback from the plugin to queue for Unity's renderer to invoke IntPtr _renderFunc = CINEVR_AndroidNative_GetRenderEventFunc(); // Dispatch the event to native plugin GL.IssuePluginEvent(_renderFunc, GLEventType.Initialize);
  16. Your C++ method in your JNI plugin JNIEXPORT jstring JNICALL

    Java_js_NativePlugin_getHiString(JNIEnv * env, jobject obj) { return env->NewStringUTF("Bonjour DevFest Nantes ! Hope you have fun"); } C/C++ from Java or Kotlin
  17. From Kotlin C/C++ from Java or Kotlin external fun getHiString():

    String From Java public native String getHiString(); From Kotlin init { System.loadLibrary("sample-jni") } From Java static { System.loadLibrary("sample-jni"); }
  18. × Support available from 2018.2 × Add your files in

    a dedicated folder in the Asset Folder × Build with Gradle only × Use the AndroidJavaObject class to call methods in your plugin Building Unity Plugins Using Java or Kotlin source files as plugins
  19. × Enable Custom Gradle Templates property on the Player window

    × Override the generated mainTemplate.gradle file × You can also provide your own settings.gradle file Building Unity Plugins Add Gradle dependencies to your Unity project
  20. × Export your Unity project with Gradle or IL2CPP as

    Build System × Enable Symlink Sources if you have Java or Kotlin source files Unity from Android Studio Exporting a Unity Project
  21. × Have a full control of the build workflow ×

    Easily add Android code × Easy library management × Modify generated code Unity from Android Studio Exporting a Unity Project
  22. UnityPlayerActivity overview public class UnityPlayerActivity extends Activity { protected UnityPlayer

    mUnityPlayer; // don't change it, referenced from native code @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); getWindow().setFormat(PixelFormat.RGBX_8888); // <-- This makes xperia play happy mUnityPlayer = new UnityPlayer(this); setContentView(mUnityPlayer); mUnityPlayer.requestFocus(); } }
  23. Override the UnityPlayerActivity public class OverrideExample extends UnityPlayerActivity { @Override

    protected String updateUnityCommandLineArguments(String cmdLine) { if (Utils.preferVulkan()) return Utils.appendCommandLineArgument(cmdLine, "-force-vulkan"); else if (Utils.preferES2()) return Utils.appendCommandLineArgument(cmdLine, "-force-gles20"); else return cmdLine; // let Unity pick the Graphics API based on PlayerSettings } }
  24. What’s next? Unity as a Library × Available with Unity

    2019.3 × Add Unity content (AR/VR, 2D/3D games) directly to your Android apps × Proper library integration
  25. public class MainUnityActivity extends OverrideUnityActivity { @Override protected void onCreate(Bundle

    savedInstanceState) { super.onCreate(savedInstanceState); goBackBtn.setOnClickListener(v -> { showMainActivity(); }); sendMsgBtn.setOnClickListener(v -> { UnitySendMessage("Cube", "ChangeColor", "yellow"); }); finishBtn.setOnClickListener(v -> { finish(); }); } } Override the OverrideUnityActivity
  26. What’s next? Unity as a Library limitations × Fullscreen rendering

    only × Only one instance of the Unity runtime is supported × You may need to adapt your plugins to work properly
  27. What’s next? Unity as a library 01 02 03 https://blogs.unity3d.com/2019/06/17/add-features-powered-by

    -unity-to-native-mobile-apps Unity as a Library https://forum.unity.com/threads/using-unity-as-a-library-in-nat ive-ios-android-apps.685195/ Using Unity as a library in native iOS/Android apps https://forum.unity.com/threads/integration-unity-as-a-library- in-native-android-app.685240/ Integration Unity as a library in native Android app
  28. Eh! What about Android from a Unity Point of view?

    random person in the audience - right now
  29. What’s next? Android from a Unity Point of View ×

    Easy to build on Android × Graphic libs support (OpenGL/Vulkan) Easy compat with ShaderLab × No need to dig into the Android documentation
  30. What’s next? Android from a Unity Point of View ×

    How it is implemented under the hood × Building UI components × Integrating Unity games into Android apps… but Unity as a library is coming
  31. Want to know more? https://developer.android.com/game Android Game Development https://medium.com/@cinemur/73ec7e83dd5c ExoPlayer

    for building powerful VR players on Cardboard and GearVR https://docs.unity3d.com/Manual/PluginsForAndroid.html Building Unity Plugins for Android