1
0

More than 3 years have passed since last update.

Unreal Engine 4 でAndroidのプロジェクト作成及びAndroidのプラグイン開発

Posted at

Android用のUnreal Engine向けのプラグイン開発に携わったので、
インストールからAndroidで実行及びAndroid JAVA層へのアクセスするプラグイン開発方法。

1.Unreal Engine 4のインストール

Unreal Engine をインストールするを参考にUnreal Engineをインストールします。

2.Unreal Engineのプロジェクトを作成する。

Unreal Engineを起動するとテンプレート選択画面が現れると思います。
ProjectBrowserSelectTemplate.png

Blankを選び次へを選択するとプロジェクトの設定画面に遷移します。
プロジェクトの設定を下記のように設定します。

設定

  • C++
  • スケーラブルな3D・2D
  • レイトレーシング無効
  • モバイル/タブレット
  • スターターコンテンツ無し

名前

  • HelloProect

ProjectBrowserSelectSetting.png

プロジェクトの作成を選択するとHelloProectが作成されHelloProectが起動されます。
HelloProect.png

3.Unreal EngineのプロジェクトをAndroidに対応させる

設定を開くと次の画面が起動します。
HelloProectSettingProjectDescription.png

プラットフォーム - Android欄を選択すると次の画面になります。
HelloProectSettingPlatformAndroid.png

プロジェクトはAndroidプラットドームに対応していませんの個所の今すぐ設定を選択すると下記のように切り替わります。
またmin SDK及びtarget SDK等も指定できます。
HelloProectSettingPlatformAndroidInput.png

この状態で実行するとAndroid端末上で動くと思います。

4.Unreal EngineでAndroidのJAVA層を呼び出すためのプラグイン作成

まずプラグインの設定メニューを開きます。
HelloProectPlugin.png

New Pluginを選択することで新しいプラグインの作成メニュー画面が表示されます。
HelloProectNewPlugin.png

空のプラグインを選択し、プラグインを名前を記入し、Create Pluginを選択すると新しいプラグインが作成されます。
下記のようにプラグインメニューの一番下に作成したプラグインがあると思います。
プラグインを有効化しましょう。
HelloProectPluginOther.png

UI上で出来る事は以上になると思います。

5.Unreal EngineでAndroidのJAVA層を呼び出すためのプラグイン開発

5.1.Unreal Engineからプラグインモジュールを取得する

root/Source/HelloProjectGameModeBase.cpp
    // 例
    FHelloWorldPluginModule& module = FHelloWorldPluginModule::Get();

5.2.プラグイン側の設定

upluginの設定

root/Plugins/HelloWorldPlugin/HelloWorldPlugin.uplugin
{
    "FileVersion": 3,
    "Version": 1,
    "VersionName": "1.0",
    "FriendlyName": "HelloWorldPlugin",
    "Description": "Sample plugin to call Android JAVA layer",
    "Category": "Other",
    "CreatedBy": "Sacred Sanctuary",
    "CreatedByURL": "",
    "DocsURL": "",
    "MarketplaceURL": "",
    "SupportURL": "",
    "CanContainContent": true,
    "IsBetaVersion": false,
    "IsExperimentalVersion": false,
    "Installed": false,
    "Modules": [
        {
            "Name": "HelloWorldPlugin",
            "Type": "Runtime",
            "LoadingPhase": "Default",
            "WhitelistPlatforms": [ "Android", "IOS", "Mac", "Win32", "Win64" ]
        }
    ]
}

プラグインのインクルード設定

root/Plugins/HelloWorldPlugin/Source/HelloWorldPlugin/HelloWorldPlugin.Build.cs
if (Target.Platform == UnrealTargetPlatform.Android) {
    // Plugin settings for Android
    PrivateIncludePaths.AddRange(
        new string[] {
            "HelloWorldPlugin/Private/Android",
        });
    string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath);
    AdditionalPropertiesForReceipt.Add("AndroidPlugin", Path.Combine(PluginPath, "HelloWorldPlugin_APL.xml"));
}

Androidアプリ側のAndroidManifest.xmlやbuild.gradleの設定

root/Plugins/HelloWorldPlugin/Source/HelloWorldPlugin/HelloWorldPlugin_APL.xml
<?xml version="1.0" encoding="utf-8"?>
<!--AndroidCamera plugin additions-->
<root xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- init section is always evaluated once per architecture -->
    <init>
        <log text="HelloWorldPlugin init"/>
        <!-- currently supports all architectures -->
    </init>

    <!-- optional updates applied to AndroidManifest.xml -->
    <androidManifestUpdates>
        <!-- How to add Permission -->
        <addPermission android:name="android.permission.INTERNET"/>

        <!-- How to add Activity -->
        <setElement result="HelloActivity" value="activity" />
        <addAttribute tag="$HelloActivity" name="android:name" value="jp.sacredsanctuary.helloworld.HelloActivity" />
        <addElement tag="application" name="HelloActivity" />

        <!-- How to add Service -->
        <setElement result="HelloService" value="service" />
        <addAttribute tag="$HelloService" name="android:name" value="jp.sacredsanctuary.helloworld.service.HelloService" />
        <addAttribute tag="$HelloService" name="android:enabled" value="true" />
        <addElement tag="application" name="HelloService" />
    </androidManifestUpdates>

    <!-- optional additions to proguard -->
    <proguardAdditions>
        <insert>
            -keep class jp.sacredsanctuary.helloworld.service.HelloFromNative {
                *;
            }
        </insert>
    </proguardAdditions>

    <!-- optional files or directories to copy to Intermediate/Android/APK -->
    <resourceCopies>
        <copyDir src="$S(PluginDir)/ThirdParty/Android/Java" dst="$S(BuildDir)" />
    </resourceCopies>

    <!--
    <buildscriptGradleAdditions>
        <insert>
            dependencies {
            }
        </insert>
    </buildscriptGradleAdditions>
    -->

    <!--  optional base build.gradle additions -->
    <buildGradleAdditions>
        <insert>
            android
            {
                // ADD COMPATIBILITY OPTIONS TO BE COMPATIBLE WITH JAVA 1.8
                compileOptions {
                    sourceCompatibility = JavaVersion.VERSION_1_8
                    targetCompatibility = JavaVersion.VERSION_1_8
                }
            }

            // ADD SENTRY ANDROID AS A DEPENDENCY
            dependencies {
                implementation "androidx.annotation:annotation:1.1.0"
            }
        </insert>
    </buildGradleAdditions>
</root>

<init></init>で初期処理に行い事を記述できます。
<androidManifestUpdates></androidManifestUpdates>にAndroidManifest.xmlへ追加する項目を記述出来ます。
<resourceCopies></resourceCopies>にソースコード元とソースコードのコピー先
<proguardAdditions></proguardAdditions>にproguard-rules.proへ追加する項目を記述出来ます。
<buildscriptGradleAdditions></buildscriptGradleAdditions>にbuild.gradleへの追加する項目を記述出来ます。
<buildGradleAdditions></buildGradleAdditions>にapp/build.gradleへの追加する項目を記述出来ます。

6.ソースコード

Unreal Engine側からAndroid Java側へのアクセスはJNIを使用して呼び出す必要があります。
JNIEnvを取得するには下記のようにして取得できます。

JNIEnv* env = FAndroidApplication::GetJavaEnv();

また、Android Java側では至る所でContextを使用しますが、ContextについてもUnreal Engineのものを使用します。
取得方法は下記のようになります。

jobject gameActivity = FAndroidApplication::GetGameActivityThis();

Android Java側の呼び出し例

// JAVA側のクラス[HelloFromNative]インスタンスを取得
jclass mClazz = FAndroidApplication::FindJavaClassGlobalRef("jp/sacredsanctuary/helloworld/service/HelloFromNative");

// 取得したクラスの呼び出すメソッド[startHelloActivityFromNative]を取得
jmethodID method = FJavaWrapper::FindStaticMethod(env, mClazz, "startHelloActivityFromNative", "(Landroid/content/Context;)V", false);

// HelloFromNativeクラスのstartHelloActivityFromNativeメソッドを呼び出す
env->CallStaticVoidMethod(mClazz, method, mContext);

これでJava側の呼び出しが可能となり、Java側を使用してAndroidのAPIを呼び出すことが出来るようになります。
Java側で処理した内容はJNIを使用してUnreal Engine側へ返すことも可能です。

今回の内容のソースコードになります。
内容はUnreal Engine側からJava層を呼び出して、Java層でActivityを開始するという至ってシンプルなものとなります。

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0