언리얼 플러그인 언어

UPL은 XML 조작 및 문자열 반환에 사용하는 간단한 XML 기반 언어입니다.

Choose your operating system:

Windows

macOS

Linux

언리얼 플러그인 언어(Unreal Plugin Language,UPL) 는 XML 조작 및 문자열 반환에 사용하는 간단한 XML 기반 언어입니다. 다른 모든 섹션보다 먼저 아키텍처당 한 번 평가되는 섹션이 포함되어 있습니다. 상태는 유지되고 다음 섹션으로 전달되어 평가되므로 섹션이 실행되는 순서가 중요합니다. UPL은 XML 수정 및 쿼리에 일반적으로 사용하는 시스템이며, 주로 플러그인이 속한 패키지의 글로벌 환경설정에 플러그인이 영향을 미칠 수 있도록 하는 데 사용됩니다. 예를 들어 UPL을 사용하면 플러그인에서 Android APK AndroidManfiest.xml 파일 또는 IOS IPA plist 파일을 수정할 수 있습니다. UBT는 또한 Android의 일부 .java 파일처럼 패키지에 대해 공통되어야 하는 파일에 포함할 문자열에 플러그인의 UPL xml 파일을 쿼리합니다.

트레이싱 활성화

인스트럭션이 플러그인 컨텍스트에서 실행되는지 확인해야 한다면, 다음을 추가하여 트레이싱을 활성화합니다.

<trace enable="true"/>

이 인스트럭션 이후 컨텍스트에서 실행되는 모든 노드는 를 실행할 때까지 로그에 기록됩니다. 이 명령으로 컨텍스트에 있는 모든 변수의 덤프를 가져올 수 있습니다.

<dumpvars/>

변수 타입

Bool, Int, String 변수 타입이 지원됩니다. 어떤 어트리뷰트든 변수를 참조할 수 있으며, 이 구문을 통해 평가 전에 같은 문자열로 바뀝니다.

$B(name) = boolean 변수 ‘name'의 값
$I(name) = integer 변수 ‘name'의 값
$S(name) = string 변수 ‘name'의 값
$E(name) = element 변수 ‘name'의 값

다음 변수는 자동으로 초기화됩니다.

$S(Output) = 섹션 평가를 위해 반환된 출력(Input으로 초기화됨)
$S(Architecture) = 타깃 아키텍처(armeabi-armv7a, arm64-v8a, x86, x86_64)
$S(PluginDir) = XML 파일이 로드되었던 디렉터리
$S(EngineDir) = 엔진 디렉터리
$S(BuildDir) = 프로젝트의 플랫폼에 해당하는 (Intermediate 폴더 내) 빌드 디렉터리
$S(Configuration) = 환경설정 유형(Debug, DebugGame, Development, Test, Shipping)
$B(Distribution) = 배포 빌드인 경우 true

위의 변수를 제외하면 전부 플러그인의 컨텍스트에 있어 네임스페이스 충돌을 방지합니다. 위에서 Output을 제외한 변수를 새 값으로 설정하려 하면 현재 컨텍스트에만 영향을 미칩니다.

변수 조작

다음 노드는 변수의 조작을 가능하게 합니다.

<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%"/>

연산자 적용의 결과로 boolean 변수가 설정될 수도 있습니다.

<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=""/>

Integer 변수에서는 이러한 산술 연산을 사용할 수 있습니다.

<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=""/>

다음을 통해 string 길이를 얻을 수 있습니다.

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

검색 string의 인덱스는 다음을 사용하여 소스에서 찾을 수 있습니다.

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

을 사용하고 결과를 확인하는 대신 다음 shortcut 문자열 비교를 사용할 수도 있습니다.

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

메시지 작성

이 노드를 사용하면 로그에 메시지가 작성됩니다.

<log text=""/>

조건식 실행

조건식 실행은 다음 양식을 사용합니다.

<if condition="">
    <true>
        <\-- Executes if boolean variable if the condition is true -->
    </true>
    <false>
        <\-- executes if boolean variable in condition is false -->
    </false>
</if>

블록은 선택사항입니다. 조건은 반드시 boolean 변수여야 합니다. boolean 연산자 노드가 결합되어 더 복잡한 조건에 대한 최종 상태를 생성할 수 있습니다.

<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>
        <\-- do something for Intel if not a distribution build -->
    </true>
</if>

"isIntel"은 다음과 같이 수행될 수 있습니다.

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

두 개의 shortcut 노드를 조건식 실행에 사용할 수 있습니다.
다음 코드는

<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/>

바디는 조건이 false이거나 에 도달할 때까지 실행됩니다. 는 조건이 여전히 true인 경우 루프의 실행을 재시작하거나 종료합니다.

<while> 바디 외부의 <break/><return></return> 과 동일한 역할을 합니다.

1~5를 로그에 쓰고 3을 건너뛰는 루프의 예시입니다. continue 이전에 while 조건의 업데이트가 이루어져야 합니다. 그렇지 않다면 루프가 종료되지 않습니다.

<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>

result 변수 이름을 생성할 때 변수 대체를 사용할 수 있습니다. 이를 통해 루프에서 배열을 생성할 수 있게 됩니다.

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

다음을 사용하여 얻을 수 있습니다. value는 변수 이름으로 취급됩니다.

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

result 변수 이름을 생성할 때 변수 대체를 사용할 수 있습니다. 이를 통해 루프에서 배열을 생성할 수 있게 됩니다.

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

다음을 사용하여 얻을 수 있습니다. value는 변수 이름으로 취급됩니다.

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

boolean과 integer 타입의 경우 및 을 사용할 수 있습니다.

텍스트 삽입

섹션에 텍스트를 삽입하는 노드는 다음과 같습니다.

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

첫 번째는 텍스트 또는 노드를 반환된 섹션 문자열에 삽입합니다. 다음 경우에는 반드시 이스케이프 문자를 사용해야 합니다.

< = <
> = >
& = &

<insertValue value=""> /pre> - 삽입 이전 값의 변수를 평가합니다. 값에 따옴표(")가 포함된 경우 따옴표를 사용하여 이스케이프해야 합니다.
<loadLibrary name="" failmsg=""> - 케이스를 로드하는 데 실패했을 때 선택적으로 로깅된 메시지를 포함한 system.LoadLibrary try/catch 블록을 삽입하는 shortcut입니다.

검색 및 대체

Output에서 다음을 사용하여 검색 및 대체를 수행할 수 있습니다.

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

$S(Output)를 직접 조작할 수도 있지만 위가 훨씬 효율적입니다.

<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=""> body </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="$"로 참조됩니다. $E(varname) 사용이 XML과 동일한 문자열로 확장되므로 Element 변수는 $varname으로 참조됩니다. 기본적으로 addElement, addElements, removeElement 는 일치하는 모든 태그에 적용됩니다. 일치하는 첫 번째 태그에만 적용되도록 once="true" 어트리뷰트가 추가될 수 있습니다.

, , 는 다음으로 업데이트됩니다.

<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에서 파일을 제거하는 것으로만 제한됩니다. 다음은 assets 디렉터리에서 Oculus Signature 파일(osig)을 제거하는 예시입니다.

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

패키징 또는 배포

다음 섹션은 패키징 또는 배포 스테이지 도중 평가됩니다.

모든 플랫폼
<\-- init section is always evaluated once per architecture -->
    <init> </init>
 Android 섹션
        <\--  optional updates applied to AndroidManifest.xml -->
    <androidManifestUpdates> </androidManifestUpdates>
        <\--  optional additions to proguard -->
    <proguardAdditions>    </proguardAdditions>
        <\--  optional AAR imports additions -->
    <AARImports> </AARImports>
        <\--  optional base build.gradle additions -->
    <baseBuildGradleAdditions>  </baseBuildGradleAdditions>
        <\--  optional base build.gradle buildscript additions -->
    <buildscriptGradleAdditions>  </buildscriptGradleAdditions>
        <\--  optional app build.gradle additions -->
    <buildGradleAdditions>  </buildGradleAdditions>
        <\--  optional additions to generated build.xml before ${sdk.dir}/tools/ant/build.xml import -->
    <buildXmlPropertyAdditions> </buildXmlPropertyAdditions>
        <\--  optional files or directories to copy or delete from Intermediate/Android/APK before ndk-build -->
    <prebuildCopies> </prebuildCopies>
        <\-- optional files or directories to copy or delete from Intermediate/Android/APK after ndk-build -->
    <resourceCopies> </resourceCopies>
        <\-- optional files or directories to copy or delete from Intermediate/Android/APK before Gradle -->
    <gradleCopies> </gradleCopies>
        <\-- optional properties to add to gradle.properties -->
    <gradleProperties> </gradleProperties>
        <\-- optional parameters to add to Gradle commandline (prefix with a space or will run into previous parameter(s)) -->
    <gradleParameters> </gradleParameters>
        <\-- optional minimum SDK API level required -->
    <minimumSDKAPI> </minimumSDKAPI>
        <\-- optional additions to the GameActivity imports in GameActivity.java -->
    <gameActivityImportAdditions> </gameActivityImportAdditions>
       <\-- optional additions to the GameActivity after imports in GameActivity.java -->
    <gameActivityPostImportAdditions> </gameActivityPostImportAdditions>
        <\-- optional additions to the GameActivity class implements in GameActivity.java (end each line with a comma) -->
    <gameActivityImplementsAdditions> </gameActivityImplementsAdditions>
        <\-- optional additions to the GameActivity class body in GameActivity.java -->
    <gameActivityClassAdditions> </gameActivityOnClassAdditions>
        <\-- optional additions to GameActivity onCreate metadata reading in GameActivity.java -->
    <gameActivityReadMetadata> </gameActivityReadMetadata>
        <\-- optional additions to GameActivity onCreate in GameActivity.java -->
    <gameActivityOnCreateAdditions> </gameActivityOnCreateAdditions>
        <\-- optional additions to GameActivity onDestroy in GameActivity.java -->
    <gameActivityOnDestroyAdditions> </gameActivityOnDestroyAdditions>
        <\-- optional additions to GameActivity onStart in GameActivity.java -->
    <gameActivityOnStartAdditions> </gameActivityOnStartAdditions>
        <\-- optional additions to GameActivity onStop in GameActivity.java -->
    <gameActivityOnStopAdditions> </gameActivityOnStopAdditions>
        <\-- optional additions to GameActivity onPause in GameActivity.java -->
    <gameActivityOnPauseAdditions> </gameActivityOnPauseAdditions>
        <\-- optional additions to GameActivity onResume in GameActivity.java -->
    <gameActivityOnResumeAdditions>    </gameActivityOnResumeAdditions>
        <\-- optional additions to GameActivity onNewIntent in GameActivity.java -->
    <gameActivityOnNewIntentAdditions> </gameActivityOnNewIntentAdditions>
        <\-- optional additions to GameActivity onActivityResult in GameActivity.java -->
    <gameActivityOnActivityResultAdditions>    </gameActivityOnActivityResultAdditions>
        <\-- optional libraries to load in GameActivity.java before 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=""/>
언리얼 엔진의 이전 버전을 위해 작성된 페이지입니다. 현재 언리얼 엔진 5 버전을 위해 업데이트되지 않았습니다.