虚幻插件语言

UPL是一种基于XML的简单语言,用于操作XML和返回字符串。

Windows
MacOS
Linux

虚幻插件语言 (UPL)是一种基于XML的简单语言,用于操作XML和返回字符串。它包含一个分段,在计算任何其他分段之前,每个架构计算一次这个分段。状态被维护并推进到下个分段进行评估,因此分段的执行顺序很重要。虽然UPL是一个用于修改和查询XML的通用系统,但它专门用于允许插件影响其所属包的全局配置。例如,它允许插件修改Android APK AndroidManfiest.xml文件或IOS IPA plist文件。UBT还将查询插件的UPL xml文件,查找文件中要包含的字符串(对于包来说必须是常见的字符串),例如Android上的一些.java文件。

启用追踪

如果需要查看在插件情境中执行的指令,请添加以下命令以启用追踪:

<trace enable="true"/>

在此指令之后,在情境中实际执行的所有节点都将写入日志,直到执行 **<trace enable="false"></trace>**。您还可以使用此命令获得情境中所有变量的转储:

<dumpvars/>

变量类型

支持Bool、Int和String变量类型。任何属性都可以引用一个变量,在使用该语法求值之前,将用等效字符串替换该变量:

$B(name) = 布尔变量“名称”值
$I(name) = 整数变量“名称”值
$S(name) = 字符串变量“名称”值
$E(name) = 元素变量“名称”值

以下变量将自动初始化:

$S(Output) = 返回用于计算分段的输出(初始化为输入)
$S(Architecture) = 目标架构(armeabi-armv7a、arm64-v8a、x86、x86_64)
$S(PluginDir) = 加载XML文件的目录
$S(EngineDir) = 引擎目录
$S(BuildDir) = 项目平台相应的构建目录(在中间文件夹中)
$S(Configuration) = 配置类型(Debug、DebugGame、Development、Test、Shipping)
$B(Distribution) = 如果是发布构建,则为true

除上述变量外,所有变量都在插件的情境中,以防止命名空间冲突;尝试将一个新值设置为上述任何一个值(输出除外)只会影响当前情境。

变量操作

以下节点允许变量操作:

<setBool result="" value=""/>
<setInt result="" value=""/>
<setString result="" value=""/>
<setElement result="" value=""/>
<setElement result="" value="" text=""/>
<setElement result="" xml=""/>
包含值的<setElement>用于创建一个空的XML元素,并将标记设置为值。
包含值和文本的<setElement>用于创建一个XML元素,并将标记设置为未解析文本的值。
包含xml的<setElement>将解析提供的XML。记住对任何特殊字符进行换码!

也可以从ini文件中的属性设置变量:

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

还可以使用节点从环境变量中设置字符串。环境变量必须指定为“value”属性,并封装在一对“%”字符中。

<setStringFromEnvVar result="" value=""/>

您还可以检查是否定义了特定的环境变量(同样,用“%”字符包装):

<setBoolEnvVarDefined result="" value=""/>

使用环境变量节点的一般示例:

<setBoolEnvVarDefined result="bHasNDK" value="%NDKROOT%"/>
 <setStringFromEnvVar result="NDKPath" value="%NDKROOT%"/>

布尔变量也可以设置为应用运算符的结果:

<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=""/>
<setBoolFromPropertyContains result="" ini="" section="" property="" contains=""/>

整数变量可以使用这些算术运算:

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

字符串是用下面的代码操作的:

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

字符串长度可以用以下代码检索:

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

搜索字符串的索引可以通过以下命令在源代码中找到:

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

还可以使用以下快捷键字符串比较,而不是使用并检查结果:

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

写入消息

使用此节点将消息写入日志:

<log text=""/>

条件执行

条件执行使用以下形式:

<if condition="">
    <true>
        <\-- 如果条件为true,且是布尔变量,则执行 -->
    </true>
    <false>
        <\-- 如果条件为false,且是布尔变量,则执行 -->
    </false>
</if>

<true><false> 块是可选的。条件必须在布尔变量中。布尔运算符节点可以组合起来,为更复杂的条件创建最终状态:

<setBoolNot result="notDistribution" source="$B(Distribution)/>
<setBoolIsEqual result="isX86" arg1="$S(Architecture)" arg2="x86"/>
<setBoolIsEqual result="isX86_64" arg2="$S(Architecture)" arg2="x86_64/">
<setBoolOr result="isIntel" arg1="$B(isX86)" arg2="$B(isX86_64)"/>
<setBoolAnd result="intelAndNotDistribution" arg1="$B(isIntel)" arg2="$B(notDistribution)"/>
<if condition="intelAndNotDistribution">
    <true>
        <\-- 如果不是发布构建,为Intel执行一些操作 -->
    </true>
</if>

“isIntel”也可以这么做:

<setStringSubstring result="subarch" source="$S(Architecture)" start="0" length="3"/>
<setBoolEquals result="isIntel" arg1="$S(subarch)" arg2="x86"/>

有两个快捷方式节点可用于条件执行:
以下代码:

<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> blah
    <\-- do stuff -->
</isDistribution>

与以下代码等效:

<if condition="Distribution">
    <\-- do stuff -->
</if>

可以使用以下代码停止执行:

<return/>

循环

可以使用这些节点创建循环:

<while condition="">
    <\-- do stuff -->
</while>
<break/>
<continue/>

<while> 主体将执行,直到条件为false或命中一个 <break/>。如果条件仍然为true或退出,<continue></continue> 将重新启动循环的执行。

<while> 主体外的 <break/> 的作用将与 <return></return> 相同。

下面是一个示例循环,它将1到5写入日志,其中跳过3。注意,while条件的更新应该在continue之前完成,否则它可能不会退出。

<setInt result="index" value="0"/>
<setBool result="loopRun" value="true"/>
<while condition="loopRun">
    <setIntAdd result="index" arg1="$I(index)" arg2="1"/>
    <setBoolIsLess result="loopRun" arg1="$I(index)" arg2="5"/>
    <setBoolIsEqual result="indexIs3" arg1="$I(index)" arg2="3"/>
    <if condition="indexIs3">
        <true>
            <continue/>
        </true>
    </if>
    <log text="$I(index)"/>
</while>

也可以使用变量替换来生成结果变量名。这使得在循环中创建数组成为可能:

<setString result="array_$I(index)" value="element $I(index) in array"/>

可以使用以下方法检索(值作为变量名处理):

<setStringFrom result="out" value="array_$I(index)"/>

也可以使用变量替换来生成结果变量名。这使得在循环中创建数组成为可能:

<setString result="array_$I(index)" value="element $I(index) in array"/>

可以使用以下方法检索(值作为变量名处理):

<setStringFrom result="out" value="array_$I(index)"/>

对于布尔和整数类型,您可以使用 <setBoolFrom><setIntFrom>

插入文本

用于将文本插入分段的节点如下所示:

<insert> 主体 </insert>
<insertNewline/>
<insertValue value=""/>
<loadLibrary name="" failmsg=""/>

第一个将在返回的分段字符串中插入文本或节点。请注意,您必须对以下符号使用换码的字符:

< = <
> = >
& = &

<insertValue value=""> /pre> - 在插入之前计算变量的值。如果值包含双引号("),则必须用引号对其进行换码。
<loadLibrary name="" failmsg=""> - 是插入system.LoadLibrary尝试/捕捉块的快捷方式,带有可选的有关加载失败案例的日志消息。

搜索和替换

您可通过以下方式在输出中进行搜索和替换:

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

您还可以直接操作实际的$S(输出),上面的方法更有效:

<setStringAdd result="Input" arg1="$S(Output)" arg2="sample\n"/>
<setStringReplace result="Input" source="$S(Output)" find=".LAUNCH" with=".INFO"/>

XML操作

XML操作使用以下节点:

<addElement tag="" name=""/>
<addElements tag=""> 主体 </addElements>
<removeElement tag=""/>
<setStringFromTag result="" tag=""/>
<setStringFromAttribute result="" tag="" name=""/>
<setStringFromTagText result="" tag=""/>
<addAttribute tag="" name="" value=""/>
<removeAttribute tag="" name=""/>
<loopElements tag=""> instructions </loopElements>

当前元素通过tag="$"引用。元素变量通过$varname引用,因为使用$E(varname)将被扩展为与XML等效的字符串。addElementaddElementsremoveElement 默认应用于所有匹配的标记。可添加到的可选once="true"属性仅应用于第一个匹配标记。

<uses-permission><uses-feature><uses-library> 使用以下方式更新:

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

上述命令中的任何属性都复制到添加到清单的元素中,以便您可以执行以下操作,例如:

<addFeature android:name="android.hardware.usb.host" android:required="true"/>

复制文件

最后,这些节点允许复制用于暂存jar和so文件的文件:

<copyFile src="" dst="" force=""/>
<copyDir src="" dst="" force=""/>

如果force为false,则只有在长度或时间戳不匹配时才替换文件。此值默认为true。

应该使用以下目录作为src和dst路径的基础:

$S(PluginDir) = 加载XML文件的目录
    $S(EngineDir) = 引擎目录
$S(BuildDir) = 项目平台相应的构建目录

虽然可以在APK目录之外写入,但不推荐这样做。

移除文件

如果必须移除文件(例如发布构建中的纯开发文件),则可以使用该节点:

<deleteFiles filespec=""/>

它仅限于从BuildDir中移除文件。下面是从资源目录中移除Oculus签名文件(osig)的示例用法:

<deleteFiles filespec="assets/oculussig_*"/>

打包或部署

在打包或部署阶段评估以下部分:

对于所有平台
<\-- 每个架构都要对init部分进行一次评估 -->
    <init> </init>
 Android特定部分
        <\--  应用于AndroidManifest.xml的可选更新 -->
    <androidManifestUpdates> </androidManifestUpdates>
        <\--  proguard的可选添加内容 -->
    <proguardAdditions>    </proguardAdditions>
        <\--  可选的AAR导入添加内容 -->
    <AARImports> </AARImports>
        <\--  可选的基础build.gradle添加内容 -->
    <baseBuildGradleAdditions>  </baseBuildGradleAdditions>
        <\--  可选的基础build.gradle构建脚本添加内容 -->
    <buildscriptGradleAdditions>  </buildscriptGradleAdditions>
        <\--  可选的应用程序build.gradle添加内容 -->
    <buildGradleAdditions>  </buildGradleAdditions>
        <\--  在${sdk.dir}/tools/ant/build.xml导入之前,对生成的build.xml的可选添加内容 -->
    <buildXmlPropertyAdditions> </buildXmlPropertyAdditions>
        <\--  在ndk构建之前可以选择从Intermediate/Android/APK复制或删除的文件或目录 -->
    <prebuildCopies> </prebuildCopies>
        <\-- 在ndk构建之后可以选择从Intermediate/Android/APK复制或删除的文件或目录 -->
    <resourceCopies> </resourceCopies>
        <\-- 在Gradle之前可以选择从Intermediate/Android/APK复制或删除的文件或目录 -->
    <gradleCopies> </gradleCopies>
        <\-- 可以选择添加到gradle.properties的属性 -->
    <gradleProperties> </gradleProperties>
        <\-- 可以选择添加到Gradle命令行的参数(带有空格的前缀或将碰到前面的参数) -->
    <gradleParameters> </gradleParameters>
        <\-- 可选的必要最小SDK API级别 -->
    <minimumSDKAPI> </minimumSDKAPI>
        <\-- GameActivity.java中的GameActivity导入的可选添加内容 -->
    <gameActivityImportAdditions> </gameActivityImportAdditions>
       <\-- GameActivity.java中的导入后可以选择向GameActivity添加的内容 -->
    <gameActivityPostImportAdditions> </gameActivityPostImportAdditions>
        <\-- GameActivity.java中的GameActivity类实现的可选添加内容(每行以逗号结尾) -->
    <gameActivityImplementsAdditions> </gameActivityImplementsAdditions>
        <\-- GameActivity.java中GameActivity类主体的可选添加内容 -->
    <gameActivityClassAdditions> </gameActivityOnClassAdditions>
        <\-- GameActivity.java中GameActivity onCreate元数据读取的可选添加内容 -->
    <gameActivityReadMetadata> </gameActivityReadMetadata>
        <\-- GameActivity.java中GameActivity onCreate的可选添加内容 -->
    <gameActivityOnCreateAdditions> </gameActivityOnCreateAdditions>
        <\-- GameActivity.java中GameActivity onDestroy的可选添加内容 -->
    <gameActivityOnDestroyAdditions> </gameActivityOnDestroyAdditions>
        <\-- GameActivity.java中GameActivity onStart的可选添加内容 -->
    <gameActivityOnStartAdditions> </gameActivityOnStartAdditions>
        <\-- GameActivity.java中GameActivity onStop的可选添加内容 -->
    <gameActivityOnStopAdditions> </gameActivityOnStopAdditions>
        <\-- GameActivity.java中GameActivity onPause的可选添加内容 -->
    <gameActivityOnPauseAdditions> </gameActivityOnPauseAdditions>
        <\-- GameActivity.java中GameActivity onResume的可选添加内容 -->
    <gameActivityOnResumeAdditions>    </gameActivityOnResumeAdditions>
        <\-- GameActivity.java中GameActivity onNewIntent的可选添加内容 -->
    <gameActivityOnNewIntentAdditions> </gameActivityOnNewIntentAdditions>
        <\-- GameActivity.java中GameActivity onActivityResult的可选添加内容 -->
    <gameActivityOnActivityResultAdditions>    </gameActivityOnActivityResultAdditions>
        <\-- GameActivity.java中加载的可选库(在libUE4.so之前) -->
    <soLoadLibrary>    </soLoadLibrary>

支持的节点

以下是支持节点的完整列表:

<isArch arch="">
<isDistribution>
<if> => <true> / <false>
<while condition="">
<return/>
<break/>
<continue/>
<log text=""/>
<insert> </insert>
<insertValue value=""/>
<replace find="" with""/>
<copyFile src="" dst=""/>
<copyDir src="" dst=""/>
<loadLibrary name="" failmsg=""/>
<setBool result="" value=""/>
<setBoolEnvVarDefined result="" value=""/>
<setBoolFrom result="" value=""/>
<setBoolFromProperty result="" ini="" section="" property="" default=""/>
<setBoolFromPropertyContains result="" ini="" section="" property="" contains=""/>
<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=""/>
<setInt result="" value=""/>
<setIntFrom result="" value=""/>
<setIntFromProperty result="" ini="" section="" property="" default=""/>
<setIntAdd result="" arg1="" arg2=""/>
<setIntSubtract result="" arg1="" arg2=""/>
<setIntMultiply result="" arg1="" arg2=""/>
<setIntDivide result="" arg1="" arg2=""/>
<setIntLength result="" source=""/>
<setIntFindString result="" source="" find=""/>
<setString result="" value=""/>
<setStringFrom result="" value=""/>
<setStringFromEnvVar result="" value=""/>
<setStringFromProperty result="" ini="" section="" property="" default=""/>
<setStringAdd result="" arg1="" arg2=""/>
<setStringSubstring result="" source="" index="" length=""/>
<setStringReplace result="" source="" find="" with=""/>
Select Skin
Light
Dark

欢迎来到全新虚幻引擎4文档站!

我们正在努力开发新功能,包括反馈系统,以便您能对我们的工作作出评价。但它目前还未正式上线。如果您对此页面有任何意见与在使用中遭遇任何问题,请前往文档反馈论坛告知我们。

新系统上线运行后,我们会及时通知您的。

发表反馈意见