Help us understand the problem. What is going on with this article?

Unreal Plugin Language リファレンス

はじめに

UE4でAndroid向けのプラグインを作るときにサードパーティのライブラリを追加したり設定ファイルを変更したいことがあります。
プラグインを組み込んだプロジェクトでそんな変更をするのは大変です。
そこでこれらの設定をビルドツールで行い、凝ったプラグインでも簡単に導入することができるようにしたものがUnreal Plugin Languageです。
以下では、利用例やリファレンスを紹介します。

追記

公式ドキュメントにもUnreal プラグイン言語が作成されています。

利用例

こまけーことはいいんだ、という人は利用例を見た方が早いかもしれません。
GitHubとUE4をインストールしたフォルダのどちらでも見れますので、両方のパスを記載します。

※UE4のソースにアクセスするためには登録が必要なので、エンジンのソースコード取得とビルド手順のまとめ UE4.6改訂版を参考にしてください。サードパーティのプラグインは登録なしに見ることができます。

  • GitHubのUE4のソース
  • インストールしたUE4のソース

    • GearVR Plugin

      [ENGINE INSTALL LOCATION]\Engine\Plugins\Runtime\GearVR\Source\GearVR\GearVR.Build.cs
      [ENGINE INSTALL LOCATION]\Engine\Plugins\Runtime\GearVR\Source\GearVR\GearVR_APL.xml
      
    • GoogleVR Plugin

      • GoogleVRController Module

        [ENGINE INSTALL LOCATION]\Engine\Plugins\Runtime\GoogleVR\GoogleVRController\Source\GoogleVRController\GoogleVRController.Build.cs
        [ENGINE INSTALL LOCATION]\Engine\Plugins\Runtime\GoogleVR\GoogleVRController\Source\GoogleVRController\GoogleVRController_APL.xml
        
      • GoogleVRHMD Plugin

        [ENGINE INSTALL LOCATION]\Engine\Plugins\Runtime\GoogleVR\GoogleVRHMD\Source\GoogleVRHMD\GoogleVRHMD.Build.cs
        [ENGINE INSTALL LOCATION]\Engine\Plugins\Runtime\GoogleVR\GoogleVRHMD\Source\GoogleVRHMD\GoogleVRHMD_APL.xml
        
  • サードパーティのプラグイン

Unreal Plugin Languageとは

Unreal Plugin LanguageはXMLベースの言語で次のような機能を提供します。

  • ファイル、フォルダのコピー(主にライブラリやリソース)
  • ファイルの削除
  • AndroidのAndroidManifest.xml、proguard、GameActivity.javaにコード追加
  • iOSのInfo.plistにコード追加

このXMLはBuild.csで読み込みます。

Build.cs

UPLの対象プラットフォームは以下の2種類です。

プラットフォーム ReceiptPropertyのプロパティ名
Android AndroidPlugin
iOS IOSPlugin

Androidの場合はGearVRやGoogleVRプラグインを真似して以下のコードでXMLを読み込めばよいでしょう。

CppTest.Build.cs
if (Target.Platform == UnrealTargetPlatform.Android)
{
    string PluginPath = Utils.MakePathRelativeTo(ModuleDirectory, BuildConfiguration.RelativeEnginePath);
    AdditionalPropertiesForReceipt.Add(new ReceiptProperty("AndroidPlugin", Path.Combine(PluginPath, "CppTest_APL.xml")));
}

Unreal Plugin Languageのリファレンス

現状、リファレンスはUnrealPluginLanguage.csにコメントで記述されたものだけなので、これを元に解説していきます。

空定義のXML

<?xml version="1.0" encoding="utf-8"?>
<root xmlns:android="http://schemas.android.com/apk/res/android">
<!-- ここに追加していく -->
</root>

デバッグ

<trace enable="true"/>

ログを有効にするかどうか設定できます。


<dumpvars/>

XMLの中で設定した変数の値をログに出力します。


<log text="..."/>

textで指定したメッセージをログに出力します。
各セクションで出力すると動作確認しやすくなります。

変数

  • $B(name) : boolean
  • $I(name) : integer
  • $S(name) : string
  • $E(name) : XMLのelement

変数nameをそれぞれの型の値として参照できます。

定義済みの変数

  • $S(Architecture) : アーキテクチャ名 (armeabi-armv7a, arm64-v8a, x86, x86_64)
  • $S(PluginDir) : XMLファイルが読み込まれたフォルダ名
  • $S(EngineDir) : エンジンのフォルダ名
  • $S(BuildDir) : プラットフォーム毎のビルドフォルダ名 (Intermediateフォルダ内)
  • $S(ProjectDir) : プロジェクトのフォルダ名
  • $B(Distribution) : Distributionビルドならtrueが設定されます。
  • $S(Output) : 後述するセクション毎にその内容が設定されるので、動的に変更することができます。

共通のセクション

init

<init></init>

アーキテクチャ毎に1回だけ実行されるセクションです。
変数を定義、操作したり<log text="..."/>でログを出したりできます。

Android用のセクション

以下のセクションはReceiptProperty()AndroidPluginを指定すると適用されます。

androidmanifestUpdates

<androidManifestUpdates>
    <addPermission android:name="..."/>
    <addFeature android:name="..."/>
    <addLibrary android:name="..."/>

    <addElement tag="..." name="..."/>
    <removeElement tag="..."/>
    <addElements tag="..."></addElements>

    <addAttribute tag="..." name="..." value="..."/>
    <removeAttribute tag="..." name="..."/>

    <loopElements tag="..."></loopElements>
</androidManifestUpdates>

[PROJECT LOCATION]/Intermediate/Android/APK/AndroidManifest.xml<uses-permission>, <uses-feature>, <uses-library>を追加します。
また、任意の要素、属性を追加、削除することもできます。

proguardAdditions

<proguardAdditions>
    <insert>...</insert>
</proguardAdditions>

タグ内で操作した内容が[PROJECT LOCATION]/Intermediate/Android/APK/proguard-project.txtに反映されます。

prebuildCopies

<prebuildCopies>
    <copyFile src="..." dst="..."/>
    <deleteFiles filespec="..."/>
</prebuildCopies>

ndk-buildで必要なライブラリやファイルをビルド前にコピーするために使います。

resourceCopies

<resourceCopies>
    <copyFile src="..." dst="..."/>
    <deleteFiles filespec="..."/>
</resourceCopies>

ndk-buildの後に必要なファイルをコピーするために使います。
JavaのビルドはAPK作成時なので、追加したいJavaのソースファイルはこれでコピーすればよいです。

AARImports

<AARImports>
    <insert>...</insert>
</AARImports>

aar-imports.txt$(Output)に読み込まれるので<insert></insert>などでAARを追加できます。

GameActivity.java更新用のセクション

ビルドターゲットにAndroidを追加すると以下のJavaソースファイルがコピーされます。

  • コピー元: [ENGINE INSTALL LOCATION]\Engine\Build\Android\java\src\com\epicgames\ue4\GameActivity.java
  • コピー先: [PROJECT LOCATION]\Intermediate\Android\APK\src\com\epicgames\ue4\GameActivity.java

このファイルはAPK作成時に独自のコードを追加するためのプレースホルダーがいくつかあり、以下のタグで操作することができます。

注意
GameActivity.javaが作られるとXMLのJavaコードを変更しても反映されません。
コピー先の方のGameActivity.javaを削除すると、次のAPK作成時に変更が反映されます。

gameActivityImportAdditions

<gameActivityImportAdditions>
    <insert>...</insert>
</gameActivityImportAdditions>

GameActivityにimportを追加するときに使います。
コピー元のプレースホルダーは$${gameActivityImportAdditions}$$です。

gameActivityClassAdditions

<gameActivityClassAdditions>
    <insert>...</insert>
</gameActivityClassAdditions>

GameActivityにメンバ変数やメンバメソッドを追加するときに使います。
コピー元のプレースホルダーは$${gameActivityClassAdditions}$$です。

gameActivityOnStartAdditions

<gameActivityOnStartAdditions>
    <insert>...</insert>
</gameActivityOnStartAdditions>

GameActivityのonStart()に処理を追加するときに使います。
コピー元のプレースホルダーは$${gameActivityOnStartAdditions}$$です。

gameActivityReadMetadataAdditions

<gameActivityReadMetadataAdditions>
    <insert>...</insert>
</gameActivityReadMetadataAdditions>

GameActivityのonCreate()でAndroidManifest.xmlから設定を読み込むときに使います。
コピー元のプレースホルダーは$${gameActivityReadMetadataAdditions}$$です。

gameActivityOnCreateAdditions

<gameActivityOnCreateAdditions>
    <insert>...</insert>
</gameActivityOnCreateAdditions>

GameActivityのonCreate()に処理を追加するときに使います。
コピー元のプレースホルダーは$${gameActivityOnCreateAdditions}$$です。

gameActivityOnDestroyAdditions

<gameActivityOnDestroyAdditions>
    <insert>...</insert>
</gameActivityOnDestroyAdditions>

GameActivityのonDestroy()に処理を追加するときに使います。
コピー元のプレースホルダーは$${gameActivityOnDestroyAdditions}$$です。

gameActivityOnStopAdditions

<gameActivityOnStopAdditions>
    <insert>...</insert>
</gameActivityOnStopAdditions>

GameActivityのonStop()に処理を追加するときに使います。
コピー元のプレースホルダーは$${gameActivityOnStopAdditions}$$です。

gameActivityOnPauseAdditions

<gameActivityOnPauseAdditions>
    <insert>...</insert>
</gameActivityOnPauseAdditions>

GameActivityのonPause()に処理を追加するときに使います。
コピー元のプレースホルダーは$${gameActivityOnPauseAdditions}$$です。

gameActivityOnResumeAdditions

<gameActivityOnResumeAdditions>
    <insert>...</insert>
</gameActivityOnResumeAdditions>

GameActivityのonResume()に処理を追加するときに使います。
コピー元のプレースホルダーは$${gameActivityOnResumeAdditions}$$です。

gameActivityOnActivityResultAdditions

<gameActivityOnActivityResultAdditions>
    <insert>...</insert>
</gameActivityOnActivityResultAdditions>

GameActivityのonActivityResult()に処理を追加するときに使います。
コピー元のプレースホルダーは$${gameActivityOnActicityResultAdditions}$$です。

soLoadLibrary

<soLoadLibrary>
    <loadLibrary name="..." failmsg="..."/>
    <insert>...</insert>
</soLoadLibrary>

GameActivityでロードしたいネイティブライブラリを追加するときに使います。
細かい処理をしたい場合は<insert></insert>を使うこともできます。
コピー元のプレースホルダーは$${soLoadLibrary}$$です。

iOS用のセクション

以下のセクションはReceiptProperty()IOSPluginを指定すると適用されます。

iosPListUpdates

<iosPListUpdates></iosPListUpdates>

このセクションの内容を[PROJECT LOCATION]/Intermediate/IOS/[GAME NAME]-Info.plistに書き出します。

各種の操作

変数定義

<setBool result="..." value="..."/>
<setInt result="..." value="..."/>
<setString result="..." value="..."/>
<setElement result="..." value="..."/>
<setElement result="..." xml="..."/>

valueの値をresultで指定した変数に代入します。


<setBoolFromProperty result="..." ini="..." section="..." property="..." default="..."/>
<setIntFromProperty result="..." ini="..." section="..." property="..." default="..."/>
<setStringFromProperty result="..." ini="..." section="..." property="..." default="..."/>

iniファイルから値を読み込みます。
ファイルやセクション、プロパティが存在しない場合はdefaultが代入されます。

演算

<setBoolNot result="..." source="..."/>
<setBoolAnd result="..." arg1="..." arg2="..."/>
<setBoolOr result="..." arg1="..." arg2="..."/>
<setBoolIsEqual result="..." arg1="..." arg2="..."/>
<setBoolIsLess result="..." arg1="..." arg2="..."/>
<setBoolIsLessEqual result="..." arg1="..." arg2="..."/>
<setBoolIsGreater result="..." arg1="..." arg2="..."/>
<setBoolIsGreaterEqual result="..." arg1="..." arg2="..."/>

論理演算した結果をresultで指定した変数に代入します。


<setIntAdd result="..." arg1="..." arg2="..."/>
<setIntSubtract result="..." arg1="..." arg2="..."/>
<setIntMultiply result="..." arg1="..." arg2="..."/>
<setIntDivide result="..." arg1="..." arg2="..."/>

算術演算した結果をresultで指定した変数に代入します。


<setStringAdd result="..." arg1="..." arg2="..."/>
<setStringSubstring result="..." source="..." start="..." length="..."/>
<setStringReplace result="..." source="..." find="..." with="..."/>

文字列操作した結果をresultで指定した変数に代入します。


<setIntLength result="..." source="..."/>

sourceの文字列の長さをresultで指定した変数に代入します。


<setIntFindString result="..." source="..." find="..."/>

sourceからfindの文字列が一致したインデックスをresultで指定した変数に代入します。


<setBoolStartsWith result="..." source="..." find="..."/>
<setBoolEndsWith result="..." source="..." find="..."/>
<setBoolContains result="..." source="..." find="..."/>

それぞれfindで指定した文字列で始まる、終わる、含んでいるかチェックした結果をresultで指定した変数に代入します。

Output変数の操作

<replace find="..." with="..."/>

変数$(Output)からfindと一致した文字列をwithの文字列で置換します。


<insert>...</insert>
<insertValue value="..."/>
<insertNewLine/>

変数$(Output)にタグ内の文字を追加します。
主にproguardAdditionsやGameActivity.javaのセクションで使います。

制御構文

<if condition="...">
    <true>
        <!-- executes if boolean variable in condition is true -->
    </true>
    <false>
        <!-- executes if boolean variable in condition is false -->
    </false>
</if>

conditionで条件を指定し、trueタグとfalseタグでそれぞれの処理を設定できます。


<isArch arch="armeabi-armv7">
    <!-- do stuff -->
</isArch>

アーキテクチャをチェックできるショートカットノードです。これは以下と同等の操作ができます。

<setBoolEquals result="temp" arg1="$S(Architecture)" arg2="armeabi-armv7">
<if condition="temp">
    <true>
        <!-- do stuff -->
    </true>
</if>

<isDistribution>
    <!-- do stuff -->
</isDistribution>

Distributionビルドかどうかチェックできます。
これもisArchと同様にショートカットです。


<return/>

ここで処理を終了します。


<while condition="...">
    <!-- do stuff -->
</while>

<break/>
<continue/>

ループ処理です。breakcontinueもあります。

XML操作

<addElement tag="..." name="..."/>
<addElements tag="..."> body </addElements>
<removeElement tag="..."/>
<setStringFromTag result="..." tag="..." name="..."/>
<setStringFromAttribute result="..." tag="..." name="..."/>
<addAttribute tag="..." name="..." value="..."/>
<removeAttribute tag="..." name="..."/>
<loopElements tag="..."> instructions </loopElements>

要素の追加および削除、属性の追加および削除、要素や属性の値を取得、繰り返し要素に対しての操作をできます。
主にAndroidManifest.xmlのintent-filterのように特定の操作が用意されていない要素を設定するために使います。

まとめ

全体を見ると結構な量がありますが、柔軟な定義をするためだと思います。
たとえばAndroid側にロジックを追加したいときはGameActivityのセクションしか使いません。
また、プラグインでなくてもプロジェクト単体でも利用できるので使える範囲は広いです。

kadinche
弊社では 2008年の会社設立当初から、一貫して VR ソリューションの研究開発に取り組んでいます。
https://www.kadinche.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away