UDN
Search public documentation:

UnrealScriptFunctionsKR
English Translation
日本語訳
中国翻译

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 홈 > 언리얼스크립트 > 언리얼스크립트 언어 참고서 > 언리얼스크립트 함수

언리얼스크립트 함수


문서 변경내역: Tim Sweeney 원저. 홍성진 번역.

개요


함수(function)란 실행했을 때 특정 전체적인 동작을 실행하는 관련 명령 집합에 이름을 붙인 것입니다. 이러한 동작은 특정 변수의 값을 설정하는 간단한 것일 수도 있고, NPC 가 따라갈 길을 계산하는 복잡한 것일 수도 있습니다. 클래스는 본래 두 가지 요소, 변수와 함수로 이루어집니다. 변수는 데이터를 담는 반면, 함수는 그 데이터의 값을 사용하거나 수정하는 동작을 합니다. 바로 그 동작이 게임에서 보이는 게임플레이를 이루는 것입니다.

함수는 속하는 오브젝트의 데이터를 사용해서 동작을 할 뿐만 아니라, 파라미터를 사용해서 데이터를 받고 반환할 수도 있습니다.

함수 선언하기


UnrealScript 에서는 새로운 함수를 선언하고 기존 함수의 새로운 버전을 작성(함수 덮어쓰기)할 수도 있습니다. 함수는 (UnrealScript 가 지원하는 변수형의) 파라미터를 하나 이상 받아, 선택적으로 값을 반환할 수 있습니다. 대부분의 함수가 UnrealScript 로 직접 작성되기는 하지만, C++ 로 구현되어 DLL 에 들어있는 함수를 UnrealScript 에서 호출할 수 있도록 선언할 수도 있습니다. 언리얼 테크놀러지는 가능한 함수 호출 조합을 모두 지원합니다. C++ 엔진은 스크립스 함수를, 스크립트는 C++ 함수를, 스크립트는 스크립트를 호출할 수 있습니다.

꽤나 간단한 함수 선언 예제입니다:

// 플레이어가 속한 팀을 구하는 함수입니다.
function byte GetTeam(Pawn PlayerPawn)
{
   return PlayerPawn.Controller.Team;
}

함수 선언은 두 부분, 시그너처(signature, 특징)와 본문으로 구성됩니다.

함수 시그너처

함수 선언의 첫 줄에는 함수를 식별하고 부르는 방법이 정의됩니다. 이것을 함수의 시그너처 라고 합니다. 시그너처로 함수의 이름, 함수 파라미터 를 통해 받을 수 있는 값, (있다면) 결과 반환 값, 함수 지정자 를 사용해서 함수에 관련이 있는 기타 정보를 지정할 수 있습니다.

가장 기본적인 함수 시그너처는 function 키워드로 (, 특수한 이벤트 함수는 event 키워드로) 시작됩니다. 그 뒤에 선택적으로 함수의 반환형, 함수 이름을 붙인 후 괄호 안에 함수 파라미터 목록을 붙입니다.

위의 선언 예제에서 시그너처 부분은:

function byte GetTeam(Pawn PlayerPawn)

이 시그너처는 GetTeam 이라는 이름의 함수에 대한 것으로, Pawn 으로의 리퍼런스를 받아들이고, (함수의 이름으로 미루어 보면 Pawn 에 전달된 팀을 나타내는) byte 값을 반환합니다.

함수에는 선언에서 함수 지정자 로 결정되는 특성을 가질 수도 있습니다. 함수 지정자는 다른 곳에 오는 경우도 있지만 보통은 시그너처의 function (또는 event) 키워드 앞에 옵니다.

함수 본문

시그너처 다음에는 그 함수에 속하는 명령이 전부 들어있는 대괄호 한 쌍이 옵니다. 이 부분을 함수의 본문 (body)이라 합니다. 함수가 호출되면 본문 안에 있는 코드가 위에서 아래 순서대로 실행됩니다. 함수의 본문 안에는 (local 키워드를 사용해서) 로컬 변수를 선언하고, 유효한 UnrealScript 코드를 실행시킬 수 있습니다. 함수 본문 실행은 return 문 또는 대괄호가 닫히면 종료됩니다.

위의 선언 예제에서 본문 부분은:

{
   return PlayerPawn.Controller.Team;
}

기본적으로 함수에서 선언하는 로컬 변수는 그 유형에 따라 0 또는 그에 준하는 값 (Bool 에는 FALSE, 오브젝트 리퍼런스에는 None 등)으로 초기화됩니다.

반환형과 값


함수는 반환형 을 지정하여 선언할 수 있습니다. 함수가 돌려주거나 계산한 결과값의 유형이라서 반환형 이라고 합니다. 본질적으로 무슨 뜻이냐면, 어느 코드 문(statement)에서 실행시킨 함수의 결과값을, 그 문에서 변수에 할당한다든가 기타 계산을 한다든가 직접 사용할 수 있다는 뜻입니다.

값을 반환하려면 함수를 선언할 때 시그너처에 반환할 값의 유형을 지정해야 합니다:

function int GetHealth(Pawn PlayerPawn)

int 값을 반환하는 함수를 선언하는 예제입니다. 어떤 UnrealScript 유형도 반환형으로 사용할 수 있습니다.

함수에서 값을 반환하려면, return 키워드에 반환할 값을 붙이면 됩니다. 이를 return 문 이라 하며, 함수의 실행을 즉시 중지하고 지정된 값을 반환합니다. 함수에 반환형이 선언된 경우, 반드시 return 문을 사용하여 값을 반환해야 합니다.

function int GetHealth(Pawn PlayerPawn)
{
   return PlayerPawn.Health;
}

예제의 return 문은 단순히 함수에 전달된 PawnHealth 변수 현재 값을 돌려주고 있습니다.

하나의 함수에 return 문이 여럿 있을 수는 있지만, 함수가 실행될 때마다 딱 하나만 사용됩니다. 함수 본문이 (제어 구조 를 사용해서) 코드가 여러 갈래 길로 나뉘는 경우, 각각의 갈래 길에는 return 문 또는 함수 본문 끝에 catch-all return 문이 위치해야 합니다.

function bool IsAlive(Pawn PlayerPawn)
{
   if(PlayerPawn.Health > 0)
   {
      return true;
   }
   else
   {
      return false;
   }
}

함수는 반환할 수 있는 Bool 값 각각에 대해 하나의 return 문을 갖습니다만, 분명한 것은 매번 Pawn 이 살아있는가 아닌가에 따라 그들 중 하나만 실행됩니다.

함수 파라미터


값을 반환하는 것에 추가로, 함수는 본문 안에서 사용할 값을 받을 수도 있습니다. 값을 받으려면 함수를 선언할 때 하나 이상의 파라미터 를 포함시켜야 합니다. 파라미터란 본질적으로 함수 안에서 사용할 수 있는 로컬 변수지만, 그 값은 함수가 실행될 때 함수 밖에서 값을 조달하여 채웁니다.

함수 파라미터는 시그너처에서 함수 이름 뒤 괄호 안에 직접 지정합니다. 각 파라미터는 유형에다 함수 안에서 파라미터를 접근하는데 쓸 이름을 붙여 선언합니다. 파라미터가 여럿이면 쉼표로 구분해서 지정하면 됩니다:

function int GetHealth(Pawn PlayerPawn)

이 예제에서는 Pawn 으로의 리퍼런스인 PlayerPawn 이라는 이름의 값을 하나 받는 함수를 선언하고 있습니다. 함수 파라미터는 UnrealScript 유형 어느 것이든 가능합니다.

파라미터는 다른 변수와 마찬가지로 파라미터 이름을 사용하여 함수 본문 안에서 접근합니다.

함수 파라미터 지정자

Out 아웃
정상적으로 함수를 호출할 때 UnrealScript 는 함수에 전해주는 파라미터 사본을 로컬에 만듭니다. 함수가 파라미터 일부를 수정해도, 전달해 준 변수에는 아무런 영향을 끼치지 못합니다. 다음 프로그램을 예로 들어 봅시다:
   function int DoSomething( int x )
   {
      x = x * 2;
      return x;
   }

   function int DoSomethingElse()
   {
      local int a, b;

      a = 2;
      log( "The value of a is " $ a );

      b = DoSomething( a );
      log( "The value of a is " $ a );
      log( "The value of b is " $ b );
   }
   
DoSomethingElse 를 호출한 결과는 다음과 같습니다:
   The value of a is 2
   The value of a is 2
   The value of b is 4
   
다른 말로 하면, DoSomething 함수는 전달된 a 변수 로컬 사본을 만지작거린 것이지, 실제 a 변수에 영향을 끼친 것이 아닙니다.

==out== 지정자는 함수더러 전달된 변수를 실제로 수정하라 이릅니다. 로컬 사본을 만들지 않구요. 이를테면 호출자에게 값을 여럿 반환시켜야 하는 함수가 있을 때 좋습니다. 호출자가 함수에 out 값인 변수를 여럿 전달하도록 할 수 있습니다. 예를 들면:
   // 벡터의 최소 최대 성분을 계산합니다.
   function VectorRange( vector V, out float Min, out float Max )
   {
   	   // 최소값을 계산합니다.
   	   if ( V.X<V.Y && V.X<V.Z ) Min = V.X;
   	   else if( V.Y<V.Z ) Min = V.Y;
   	   else Min = V.Z;

   	   // 최대값을 계산합니다.
   	   if ( V.X>V.Y && V.X>V.Z ) Max = V.X;
   	   else if( V.Y>V.Z ) Max = V.Y;
	   else Max = V.Z;
   }
   
out 키워드 없이는 값을 둘 이상 반환시켜야 하는 함수를 작성하기가 매우 괴로울 것입니다. out 파라미터는 리퍼런스로 전달되기에, 함수에서 그 값을 바꾸면 원본에 즉시 영향을 끼치게 됩니다. C++ 와 비슷하게, "const out" 을 지정하여 큰 값에 대한 최적화로 사용할 수도 있습니다.
Optional 옵션
optional 키워드로 특정 함수 파라미터를 옵션으로 만들어 호출자의 편의를 도모할 수 있습니다. UnrealScript 함수의 경우, 호출자가 지정하지 않은 옵션 파라미터는 함수 선언에 지정된 디폴트 값, 또는 함수 시그너처에 지정된 값이 없는 경우 0 (, false, "", none 등)으로 설정됩니다. 네이티브 함수의 경우, 옵션 파라미터의 디폴트 값은 함수에 따라 달라집니다. 예를 들어 Spawn 함수는 옵션 위치와 로테이션을 받으며, 그 디폴트는 스폰되는 액터의 위치와 로테이션입니다. 옵션 인수의 디폴트 값은 = 값 을 추가하여 지정할 수 있습니다. 예를 들면 function myFunc(optional int x = -1) 식입니다.
Coerce 강제
coerce 키워드는 호출자의 파라미터를 (정상적으로는 UnrealScript 가 자동 변환하려 하지 않는 경우에도) 지정된 유형으로 강제 변환시킵니다. 문자열을 다루는 함수에서 파라미터가 자동으로 문자열로 변환되도록 하기에 좋습니다. (Strings In UnrealScript KR 참고.)

함수 지정자


Static 스태틱
스태틱 함수는 클래스의 오브젝트에 대한 리퍼런스가 없어도 호출 가능하다는 점에서 C 전역 함수처럼 작동합니다. 스태틱 함수는 다른 스태틱 함수를 호출하거나 변수 디폴트 값을 접근할 수 있습니다. 스태틱 함수는 비-스태틱 함수를 호출할 수 없으며, (오브젝트의 인스턴스와 관련해서 실행 불가능하기 때문에) 인스턴스 변수를 접근할 수도 없습니다. C++ 같은 언어와는 달리, 스태틱 함수는 가상(virtual) 클래스라 자손 클래스에서 덮어쓸 수 있습니다. (컴파일 시간에는 알려지지 않았지만, 변수나 표현식에 의해 리퍼런스되는) 가변 클래스에서 스태틱 함수를 호출하고자 할 때 좋습니다.
Singular 싱귤러
함수 선언 직전에 나타나는 singular 키워드는, 함수의 재귀적(자기) 호출을 막습니다. 규칙은 이렇습니다: 특정 액터가 이미 싱귤러 함수 가운데 있는 경우, 이후의 싱귤러 함수 호출은 생략됩니다. 무한-재귀 버그를 방지하는 데 좋습니다. 예를 들어 Bump 함수 안으로 액터를 이동하려는데, 그 와중에 그 액터가 다른 액터로 Bump 할 확률도 충분히 있으며, 그렇게 되면 Bump 함수가 계속해서 호출되게 됩니다. 매우 신중히 그렇게 되지는 않도록 해야 겠지만, 그런 재귀적 상황을 막을수 있다는 확신이 들지 않는 경우에는 singular 키워드를 사용하십시오. 참고로 이 기능은 현재 실행중인 싱귤러 함수 내에 있다면, 그 옵션이 붙은 함수에만 제한되는 것이 아니라 단일 오브젝트 내 모든 싱귤러 함수에 적용됩니다.
Native 네이티브
UnrealScript 함수는 native 로 선언 가능한데, 무슨 뜻이냐면 UnrealScript 에서 호출은 할 수 있으되 실제로는 (다른 곳의) C++ 로 구현됨을 뜻합니다. 예를 들어 Actor 클래스에는 다음과 같은 네이티브 함수 정의가 많이 들어 있습니다:
   native(266) final function bool Move( vector Delta );
   
native 키워드 뒤 괄호 안의 숫자는 (AUTOREGISTER_NATIVE 매크로를 사용하여) C++ 로 선언된 함수 번호에 해당하며, 연산자(operator) 함수에서만 필요합니다. 네이티브 함수는 보통 UnrealScript 정의가 들어있는 클래스 패키지 이름과 동일한 DLL 안에 상주해 있습니다.
NoExport 익스포트 없음
네이티브 함수에만 사용됩니다. 이 네이티브 함수에 대한 C++ 함수 선언을 익스포트하지 말 것을 선언합니다. 함수의 glue 버전에 대한 선언만 익스포트됩니다.
Exec 실행
이 함수는 콘솔에 함수 이름을 입력하여 실행시킬 수 있음을 나타냅니다. 특정 클래스에서만 사용 가능합니다.
Latent 잠복성
네이티브 함수가 잠복성임을 선언합니다. 무슨 뜻이냐면 스테이트 코드에서만 호출 가능하고, 일정한 게임 시간이 흐른 뒤 결과를 반환함을 뜻합니다.
Iterator 반복처리기
네이티브 함수가 반복처리기임을, 즉 foreach 명령을 사용하여 액터 목록을 대상으로 반복 처리하는 데 사용할 수 있는 함수임을 선언합니다.
Simulated 시뮬레이션
액터가 시뮬레이션되거나 자율적으로 처리되는 프록시일 때 클라이언트 측에서 실행할 수 있는 함수임을 선언합니다. 모든 네이티브 함수는 자동으로 시뮬레이션되기도 합니다. (주: 가상 네이티브 함수를 비-네이티브 함수로 덮어쓴 경우, 이 키워드를 지정하지 않으면 덮어쓴 비-네이티브 함수는 시뮬레이션되지 않습니다.)
Server 서버
로컬 클라이언트에서 실행되지 않고 서버에 실행을 전송시키는 함수임을 선언합니다.
Client 클라이언트
서버에서 실행되지 않고 소유한 클라이언트에 실행을 전송시키는 함수임을 선언합니다. 이 옵션은 함수에 묵시적으로 simulated 옵션을 설정하기도 합니다.
Reliable 신뢰
(serverclient 로 마킹된) 리플리케이션 함수는 신뢰 전송임을, 즉 반대편에 도달할 때 해당 액터에 대한 다른 리플리케이션과의 순서를 반드시 지켜야 하는 함수임을 선언합니다.
Unreliable 비신뢰
(serverclient 로 마킹된) 리플리케이션 함수는 비신뢰 전송임을, 즉 반대편에 도달할 때 어떤 순서를 지키거나 전혀 지키지 않아도, 심지어 대역폭이 충분치 않으면 완전히 생략해도 되는 함수임을 선언합니다.
Private, Protected 프라이빗, 프로텍티드
이 키워드는 그에 상응하는 키워드와 같은 뜻을 지닙니다.
Operator, PreOperator, PostOperator 연산자, 전위연산자, 후위연산자
(C++ 연산자에 대응하는) 연산자라 불리는 특별한 종류의 함수를 선언하는 키워드입니다. 이 방법을 통해 UnrealScript 가 "+", "-", "==", "||" 같은 내장 연산자를 전부 인식합니다. 이 글에서는 연산자 작업에 대해 자세히 다루지 않겠습니다만, 연산자에 대한 개념은 C++ 와 비슷해서 UnrealScript 함수나 네이티브 함수로 새로운 연산자와 키워드를 선언할 수 있습니다.
Event 이벤트
네이티브 C++ 엔진 코드에서 실행시킬 수 있는 함수를 선언할 때 function 키워드 대신 사용합니다. 자세한 정보는 이벤트 부분을 참고하시기 바랍니다.
Const
네이티브로 선언된 함수하고만 사용할 수 있으며, 함수 선언 뒤에 추가해야 하는 지정자입니다. 이 함수를 생성되는 헤더에 'const' 로 익스포트할 것인지 결정하는 지정자입니다. 예:
   native function int doSomething(string myData) const;
   

함수 덮어쓰기 (overriding)


함수 덮어쓰기 란 서브클래스에서 새로운 버전의 함수를 작성하는 것을 말합니다. 예를 들어 Demon 이라는 새로운 종류의 몬스터 스크립트를 작성한다 칩시다. 방금 만든 Demon 클래스는 Pawn 클래스를 확장(extends)합니다. 이제 폰이 플레이어를 처음 봤을 때 폰의 SeePlayer 함수가 호출되어 폰이 플레이어를 공격하도록 합니다. 멋진 개념이지만, 새로운 Demon 클래스에서는 SeePlayer 를 다르게 처리한다고 가정해 봅시다. 어떻게 해야 할까요? 함수 덮어쓰기가 답입니다.

함수를 덮어쓰려면 그냥 부모 클래스에서 함수 정의를 잘라다가 새로운 클래스에 붙여넣고 본문을 수정하기만 하면 됩니다. 클래스 내 함수에 대한 시그너처는 이름, 지정자, 반환형, 파라미터에 한해서 부모 클래스의 시그너처와 일치해야 합니다. (파라미터의 이름은 바꿔도 갯수와 유형은 같아야 합니다.) 예를 들어 SeePlayer 의 경우 이런 식으로 Demon 클래스에 추가하면 됩니다:

// Touch 함수의 Demon 클래스 버전입니다.
function SeePlayer( actor SeenPlayer )
{
	log( "The demon saw a player" );
   	// 여기에 새로운 커스텀 함수성 추가...
}

함수 덮어쓰기는 새로운 UnrealScript 클래스를 효율적으로 만드는 데 있어 핵심입니다. 기존 클래스를 확장하는 클래스를 새로 만들 수 있습니다. 그리고서 다르게 처리하고픈 함수만 덮어써 주면 됩니다. 이런 식으로 엄청난 양의 코드를 작성하지 않고도 새로운 종류의 오브젝트를 만들 수 있는 것입니다.

UnrealScript 의 여러 함수는 final 로 선언됩니다. (function 단어 바로 앞에 오는) final 키워드는 "이 함수는 자손 클래스가 덮어쓸 수 없습니다" 하는 것입니다. 아무도 덮어쓰지 못하게 할 함수에 사용하여, 스크립트 코드 실행을 더욱 빠르게 하는 데 쓰입니다. 예를 들어 VectorSize 라는, 벡트 크기를 계산하는 함수가 있다 칩시다. 이 함수를 덮어쓸 이유는 전혀 없을테니, final 로 선언합니다. 반면 Touch 같은 함수는 매우 맥락 의존적이므로 파이널로 하지 않는 것이 좋습니다.

함수 실행하기


함수는 함수 호출 (call)을 통해 실행됩니다. 함수 호출은 함수 이름 뒤 괄호 속에다 함수에 (파라미터로) 전해줄 데이터를 쉼표로 구분하여 지정하는 식으로 이루어집니다.

아래 함수를 예로 들어 봅시다:

function SetCollision( optional bool bNewColActors, optional bool bNewBlockActors, optional bool bNewIgnoreEncroachers );

액터에 모든 콜리전을 켜려면, 이런 식으로 함수를 호출하면 됩니다:

SetCollision(true, true, true);

호출하려는 함수에 옵션 파라미터가 들어있는 경우, 그 일부나 전부를 함수 호출시 생략할 수도 있습니다. 어느 한 파라미터를 생략한 이후에 파라미터를 붙이려면, 생략된 파라미터마다 쉼표를 찍어줘야 합니다.

예를 들어 Trace() 함수에는 옵션 파라미터가 여러 개 있습니다:

/**
 * 선 트레이스를 해서 처음 충돌하는 것을 알아봅니다.
 * 이 액터의 콜리전 프로퍼티를 고려합니다.
 * 처음 걸린 액터, 레벨에 걸렸으면 레벨, 안걸렸으면 None 을 반환합니다.
 */
function Actor Trace
(
	out vector				HitLocation,
	out vector				HitNormal,
	vector					TraceEnd,
	optional vector				TraceStart,
	optional bool				bTraceActors,
	optional vector				Extent,
	optional out TraceHitInfo		HitInfo,
	optional int				ExtraTraceFlags
);

TraceStart, bTraceActors 파라미터는 생략하고 Extent 파라미터는 붙인 채 함수를 호출하려면 (HitLocation, HitNormal, End 는 모두 예전에 선언된 로컬 Vector 변수라 가정하고,) 이런 식입니다 :

Trace(HitLocation, HitNormal, End,,,vect(4,4,4));

함수 호출 지정자


복잡한 프로그래밍 상황에서는 종종 현재 영역에 있는 함수가 아닌 특정 버전 함수를 호출해야 할 때가 있습니다. 이런 경우의 처리를 위해 UnrealScript 에는 다음과 같은 키워드가 있습니다:

Global 글로벌, 전역
가장 많이 파생된 (비-스테이트) 버전 함수를 호출합니다.
Super 수퍼, 상위
이 클래스의 부모 클래스 버전을 호출합니다. 맥락에 따라 스테이트가 될 수도 아닐 수도 있습니다.
Super(classname)
이 클래스의 지정된 클래스 (이상)에 상주하는 버전을 호출합니다. 맥락에 따라 스테이트가 될 수도 아닐 수도 있습니다.

호출 지정자를 (Super(Actor).Global.Touch 와 같은 식으로) 여럿 조합할 수는 없습니다.

호출 지정자 예제입니다:

class MyClass extends Pawn;

function MyExample( actor Other )
{
   Super(Pawn).Touch( Other );
      Global.Touch( Other );
      Super.Touch( Other );
}

부가적인 예제로 BeginPlay() 함수는 액터가 게임플레이에 들어가기 직전 호출됩니다. BeginPlay() 함수는 Actor 에 구현되어 있으며, 실행에 필요한 중요 함수성이 약간 들어 있습니다. 이제 새로운 MyClass 에서 함수성을 약간 추가하기 위해 BeginPlay() 를 덮어쓴다 쳐 봅시다. 그 작업을 안전하게 하려면 부모 클래스의 BeginPlay() 버전을 호출해 줘야 합니다:

class MyClass extends Pawn;

function BeginPlay()
{
	// 부모 클래스에 있는 BeginPlay 버전을 호출합니다 (중요).
   	Super.BeginPlay();

   	// 이제 커스텀 BeginPlay 작업을 합니다.
   	//...
}

이벤트


어떤 UnrealScript 함수는 이벤트가 발생할 때마다 엔진에 의해 호출됩니다. 이러한 함수, 또는 이벤트는 보통의 function 키워드가 아닌 event 키워드를 사용하여 선언되므로 쉽게 알아볼 수 있습니다.

예를 들어 한 액터가 다른 액터에 접할 때, 뭐가 접하는지 알려주기 위해 엔진은 그 Touch 이벤트를 호출합니다.

event Touch( Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal );

커스텀 Touch 함수를 작성하여, 접한 결과 벌어지는 특수한 동작을 취할 수 있습니다:

// 무언가 이 액터에 접했을 때 호출됩니다.
function Touch( actor Other )
{
	`log( "I was touched!")
   	Other.Message( "You touched me!" );
}

위 함수는 여러가지를 나타냅니다. 우선 함수는 (형식 규칙만 달랐지 Basic 의 print 명령이자 C 의 printf 명령인) `log 명령을 사용하여 로그 파일에 메시지를 출력합니다. 그 다음, Other 액터에 상주해 있는 "Message" 함수를 호출합니다. 다른 액터에 있는 함수를 호출하는 것은 UnrealScript 나 Java 같은 객체지향형 언어에서 일반적으로 많이 있는 일입니다. 액터끼리의 통신이 간단해 지기 때문입니다.

함수 재귀


함수는 재귀적으로 호출 가능합니다. 자기 자신을 호출할 수 있다는 뜻입니다. 어떤 작업을 하기 위한 코드 복잡도를 줄이고자 할 때, 이런 기능이 필요하거나 유용한 상황이 많이 있습니다.

예를 들어 다음 함수는 한 숫자의 계승(factorial)을 계산합니다:

// 한 숫자의 계승을 계산하는 함수입니다.
function int Factorial( int Number )
{
	if( Number <= 0 )
      	return 1;
   	else
      	return Number * Factorial( Number - 1 );
}

스태틱 함수


가변 클래스의 스태틱(정적) 함수는 다음 문법을 통해 호출할 수 있습니다:

var class C;
var class PC;

class'SkaarjTrooper'.static.SomeFunction();	// 특정 클래스에 있는 
                                        	// 스태틱 함수를 호출합니다.

PC.static.SomeFunction();	// 가변 클래스에 있는 스태틱 함수를 호출합니다.

class(C).static.SomeFunction();		// 형 변환된 클래스 표현식 내의 
                                      	// 스태틱 함수를 호출합니다.

타이머


타이머는 시간에 따라 이벤트를 발생 또는 재발생시키는 스케쥴을 잡기 위한 메커니즘으로 사용됩니다. 게임 엔진이 Timer() 함수를 한 번이든, 일정한 시간이 지난 후 반복적으로든 호출되게 하여, 액터에 스스로를 등록시키는 타이머를 설정할 수 있습니다.

UnrealScript 타이머는 그저 각 액터 내 구조체 배열로 구현됩니다 (한 액터는 타이머를 여럿 가질 수 있습니다). 구조체에는 타이머 완료시까지 남은 시간, 완료시 호출할 함수 등이 담깁니다.

게임 루프는 정상적으로 프레임마다 한 번씩 각 액터를 틱(tick) 하며, 각 액터의 Tick() 함수에는 완료된 타이머가 있는지 검사하여 적절한 UnrealScript 함수를 호출하는 UpdateTimers() 호출을 포함합니다.

입상도(granularity, 시스템을 얼마나 잘게 쪼갤 수 있는지를 나타내는 정도)는 프레임 델타(경과) 시간으로 제한되지만, 요구되는 하드웨어나 OS 리소스 제한은 없습니다. 이 모든 것은 C++ 로 구현되므로, UnrealScript 타이머는 걱정할 것 없이 수백개씩 업데이트해도 안전합니다. 물론 완료 시점에서는 (느린) 스크립트 코드가 실행되므로, 동시에 완료되게 한다던가 매 프레임마다 완료되게 하는 것은 좋지 않습니다.

타이머 함수는 Actor 서브클래스에서만 사용할 수 있습니다.

속도가 각기 다른 타이머를 여럿 만들 수 있습니다. 각 타이머는 (디폴트가 Timer() 인) 고유 타겟 함수를 갖습니다.

function SetTimer(float inRate, optional bool inbLoop, optional Name inTimerFunc)
inRate 초 후 발동되는 타이머를 시작시킵니다. inbLoop 가 참이면 타이머는 반복됩니다. inTimerFunc 는 호출할 함수를 정의하며, 디폴트는 Timer() 함수이고, 이 값은 여러 타이머를 식별하는데도 사용됩니다.
ClearTimer(optional Name inTimerFunc)
돌아가는 타이머를 멈춥니다.
bool IsTimerActive(optional Name inTimerFunc)
주어진 타이머가 살아있으면 참을 반환합니다.
float GetTimerCount(optional Name inTimerFunc)
타이머의 카운터 값, 즉 지난 번 타이머 실행 이후 지난 초를, 타이머가 살아있지 않으면 -1 을 반환힙니다.
float GetTimerRate(optional name TimerFuncName = 'Timer')
타이머 속도를 반환합니다. GetTimerRate('SomeTimer') - GetTimerCount('SomeTimer') 로 타이머에 남은 시간을 구할 수 있습니다.

내장 함수


언리얼 오브젝트 계층구조 내 가장 기본적인 (Object, Actor 등의) 클래스에서 찾을 수 있는 함수 중에는, 암기해 두면 UnrealScript 로 자신의 게임에 쓸 새로운 클래스를 만들 때 아주 유용하고 편리하게 쓸 수 있는 함수가 많이 있습니다.

오브젝트 만들기

UnrealScript 로 새로운 오브젝트 인스턴스를 만들려면, 오브젝트가 Actor 냐 아니냐에 따라 두 가지 함수 중 하나를 사용하게 됩니다. Actor 인 경우 Actor.uc 에 선언되어 있는 Spawn 함수를 사용해야 합니다. Actor 에서 파생되지 않은 클래스의 경우, new 연산자를 사용해야 합니다. new 연산자의 문법은 다른 함수와 같지 않습니다. 옵션 파라미터 목록에 더해, 새로운 오브젝트 클래스와 옵션 템플릿 오브젝트를 지정해야 합니다. new 연산자에 대한 UnrealScript 선언은 없으나, 함수 시그너처는 이렇습니다:

native final operator function coerce Object new
(
   object   InOuter,
   name     InName,
   int      InFlags,
   class    InClass,
   object   InTemplate
);

InOuter
(옵션) 새로이 생성되는 오브젝트에 대해 Outer 로 할당할 오브젝트입니다. 지정되지 않으면 오브젝트의 Outer 는 게임이 실행중일 때만 존재하는 특수 패키지, 소위 "휘발성(transient) 패키지"로 설정됩니다.
InName
(옵션) 새로운 오브젝트에 지어줄 이름입니다. 지정되지 않으면 오브젝트에는 ClassName_## 식으로, ## 는 이 클래스의 인스턴스가 생성될 때마다 증가되는 번호로, 고유한 이름을 지어줍니다.
InFlags
(옵션, 오브젝트 플랙이 64 비트가 되어 현재 깨짐) 오브젝트 생성시 사용할 오브젝트 플랙입니다. 유효한 값은:
  • 0x0000000100000000 - 에디터 되돌리기/다시하기를 지원합니다. (RF_Transactional)
  • 0x0000000400000000 - 외부 파일에서 참조 가능합니다. (RF_Public)
  • 0x0000400000000000 - 디스크에 저장할 수 없습니다. (RF_Transient)
  • 0x0010000000000000 - 게임 클라이언트에는 오브젝트를 로드하지 않습니다. (RF_NotForClient)
  • 0x0020000000000000 - 게임 서버에는 오브젝트를 로드하지 않습니다. (RF_NotForServer)
  • 0x0040000000000000 - 에디터에서는 오브젝트를 로드하지 않습니다. (RF_NotForEdit)
  • 0x0008000000000000 - 참조되지 않았어도 오브젝트를 편집 가능하도록 유지합니다. (RF_Standalone)
InClass
이 클래스의 인스턴스를 만듭니다.
InTemplate
새 오브젝트의 프로퍼티 값을 초기화시키는 데 사용할 오브젝트입니다.

new 연산자에 대한 실제 문법은 다음과 같습니다:

ObjectVar = new[(InOuter, InName, InFlags)] <class'InClass'>[(InTemplate)];

LightFunction 클래스의 오브젝트를 만듭니다:

function CreateALight()
{
   local LightFunction NewObj;

   NewObj = new class'Engine.LightFunction';
}

이 오브젝트를 Outer 로 할당하여 "NewLight" 라는 이름의 LightFunction 오브젝트를 만듭니다.

function CreateALight()
{
   local LightFunction NewObj;

   NewObj = new(Self,'NewLight') class'Engine.LightFunction';
}

새로운 오브젝트의 프로퍼티를 초기화시키는 LightFunctionTemplate 변수값으로 할당된 오브젝트를 사용하여, 휘발성(transient) 패키지에 "NewLight" 라는 이름의 LightFunction 오브젝트를 새로 만듭니다:

var LightFunction LightFunctionTemplate;

function CreateALight()
{
   local LightFunction NewObj;

   NewObj = new(None,'NewLight') class'Engine.LightFunction' (LightFunctionTemplate);
}

defaultproperties
{
   Begin Object Class=LightFunction Name=MyLightFunctionArchetype
   End Object
   LightFunctionTemplate=MyLightFunctionArchetype
}

정수 함수

int Rand( int Max )
0 에서 Max-1 사이의 난수를 반환합니다.
int Min( int A, int B )
두 수 중 최소치를 반환합니다.
int Max( int A, int B )
두 수 중 최대치를 반환합니다.
int Clamp( int V, int A, int B )
A 에서 B 까지 범위로 첫 수 V 를 제한시킨 값을 반환합니다.

경고 - C 나 C++ 에서와는 달리, Min 과 Max 는 정수에서 돌아갑니다. float 에 쓴다고 경고가 뜨지는 않으며, 수가 그냥 반내림됩니다! float 의 경우 FMin 과 FMax 를 사용해야 합니다.

부동 소수점 함수

float Abs( float A )
절대값을 반환합니다.
float Sin( float A )
라디안 수치의 사인을 반환합니다.
float Cos( float A )
라디안 수치의 코사인을 반환합니다.
float Tan( float A )
라디안 수치의 탄젠트를 반환합니다.
float ASin( float A )
라디안 수치의 역사인을 반환합니다.
float ACos( float A )
라디안 수치의 역코사인을 반환합니다.
float Atan( float A )
라디안 수치의 역탄젠트를 반환합니다.
float Exp( float A )
상수 "e" 의 A 제곱을 반환합니다.
float Loge( float A )
("e" 를 밑으로 하는) A 의 로그를 반환합니다.
float Sqrt( float A )
A 의 제곱근을 반환합니다.
float Square( float A )
A 의 제곱 = A*A 를 반환합니다.
float FRand()
0.01 에서 1.0 까지의 난수를 반환합니다.
float FMin( float A, float B )
두 수 중 작은 수를 반환합니다.
float FMax( float A, float B )
두 수 중 큰 수를 반환합니다.
float FClamp( float V, float A, float B )
A 에서 B 까지 범위로 첫 수 V 를 제한시킨 값을 반환합니다.
float Lerp( float A, float B, float Alpha )
A 와 B 사이의 선형 보간을 반환합니다.
float Smerp( float Alpha, float A, float B )
A 와 B 사이의 알파-스무드 비선형 보간을 반환합니다.
float Ceil( float A )
소수점을 올립니다.
float Round( float A )
정상적으로 반올림합니다.

문자열 함수

int Len( coerce string S )
스트링 길이를 반환합니다.
int InStr( coerce string S, coerce string t)
첫째 스트링에 둘째 문자열이 존재하면 그 위치 차이를, 아니면 -1 을 반환합니다.
string Mid( coerce string S, int i, optional int j )
스트링 S 의 i 번째 글자부터 j (가 지정되지 않으면 전부, 아니면 j) 개 글자만큼 중간 부분을 반환합니다.
string Left( coerce string S, int i )
S 의 왼쪽 i 개 글자를 반환합니다.
string Right( coerce string] S, int i )
S 의 오른쪽 i 개 글자를 반환합니다.
string Caps( coerce string S )
S 를 대문자로 변환한 것을 반환합니다.
string Locs( coerce string S)
S 의 소문자 표현을 반환합니다. (v3323 이상)
string Chr( int i )
ASCII 테이블에서 글자를 반환합니다.
int Asc( string S )
글자의 ASCII 값을 반환합니다. (스트링의 첫 글자만 사용됩니다)
string Repl( coerce string Src, coerce string Match, coerce string With, optional bool bCaseSensitive )
Src 의 Match 를 With 로 바꿉니다. (v3323 이상)
string Split( coerce string Text, coerce string SplitStr, optional bool bOmitSplitStr )
Text 를 SplitStr 이 처음 나타나는 곳에서 분리한 다음 Text 나머지 부분을 반환합니다. bOmitSplitStr (분리 문자열 생략)이 참이면 SplitStr 은 반환되는 스트링에서 제거됩니다.
array<string> SplitString( string Source, optional string Delimiter=",", optional bool bCullEmpty )
하나의 표현식을 사용하여 스트링을 스트링 배열로 분리해 넣는 감싸개 입니다.
JoinArray(array<string> StringArray, out string out_Result, optional string delim = ",", optional bool bIgnoreBlanks = true)
옵션으로 빈 멤버를 무시하고 지정된 구분자를 사용하여 스트링 배열에서 하나의 스트링을 만듭니다.
ParseStringIntoArray(string BaseString, out array<string> Pieces, string Delim, bool bCullEmpty)
구분된 스트링을 스트링 배열 요소로 쪼개 넣습니다.
A == B
두 스트링을 (대소문자 구분해서) 비교하여 같으면 참을 반환합니다.
A ~= B
두 스트링을 (대소문자 구분없이) 비교하여 같으면 참을 반환합니다.
A != B
두 스트링을 (대소문자 구분해서) 비교하여 다르면 참을 반환합니다.

자세한 정보는 Strings In UnrealScript KR 페이지를 참고하시기 바랍니다.

벡터 함수

vector vect( float X, float Y, float Z )
주어진 성분을 가지고 새로운 벡터를 만듭니다.
float VSize( vector A )
벡터의 유클리드 크기(성분 합의 제곱근을 제곱한 것)를 반환합니다.
vector Normal( vector A )
지정된 벡터 방향을 향하는 크기 1.0 의 벡터를 반환합니다.
Invert( out vector X, out vector Y, out vector Z )
축 벡터 셋으로 지정된 좌표계를 반전시킵니다.
vector VRand ()
균등 분포된 랜덤 벡터를 반환합니다.
vector MirrorVectorByNormal( vector Vect, vector Normal )
지정된 노멀 벡터를 중심으로 벡터를 미러링합니다.

디버깅 함수

다음 함수는 코드 디버깅에 도움이 됩니다.

LogEx( ELoggingSeverity Severity, name Category, coerce string Msg )
주어진 심각성(severity)과 범주에 따라 로그 메시지를 기록합니다. 이 함수는 표준 log() 함수보다 제어할 수 있는 것이 많습니다. 실행시간에 심각성과 범주에 따라 로그 메시지를 필터링할 수 있습니다.
LogFatal( name Category, coerce string Msg )
LogEx(LOG_FATAL, Category, Msg) 호출을 줄인 것입니다.
LogError( name Category, coerce string Msg )
TODO
function LogWarn( name Category, coerce string Msg )
TODO
LogInfo( name Category, coerce string Msg )
TODO
LogDebug( name Category, coerce string Msg )
TODO
LogTrace( name Category, coerce string Msg )
TODO

changelist 134102 부로 더이상 위의 로깅 함수를 사용할 수 없습니다. UnrealScript Preprocessor 에 의해 처리되는 로깅 매크로로 대체되었습니다.

ScriptTrace()
현재 스크립트 콜백을 로그 파일에 덤핑합니다.
Name GetFuncName()
현재 호출중인 함수 이름을 반환합니다.
DumpStateStack()
현재 스테이트 스택을 기록합니다.