UDN
Search public documentation:

UnrealScriptVariablesJP
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 ホーム > UnrealScript > UnrealScript 言語のリファレンス > UnrealScript の変数

UnrealScript の変数


概要


クラスに属しているプロパティは、 変数 と言います。変数とは基本的に、プレイ中に値が代入されたり変更されたりするデータを識別するもの、あるいは、そのデータのための名前のことです。プレイヤーのヘルス値や武器の弾薬数、ゲームのスコアなどの値は、何らかのクラスに属している変数の中に保持されます。これらの変数や他の変数の値を改変したり、それら値にアクセスしたりすることが、ゲーム内においてゲームプレイの重要な要素となっています。

変数のスコープ


UnrealScript で宣言できる変数には 2 種類あります。その違いは、変数の意図されたスコープによります。変数のスコープによって、変数のライフタイムと、変数が利用できる場所が決まります。

以下が、その 2 種類の変数です。

  • インスタンス変数 - インスタンス変数は、オブジェクト全体 (クラスまたは構造体) に渡るものであり、インスタンス変数が所属するオブジェクトのライフタイムの間使用することができます。インスタンス変数が作成されるのは、そのオブジェクトが作成された時であり、破棄されるのは、オブジェクトが破棄された時です。インスタンス変数は、オブジェクトに所属する非静的な関数の内部で使用することができるとともに、インスタンス変数が所属するオブジェクトへの参照を使うことによって、他のオブジェクトからもアクセスすることができます。
  • ローカル変数 - この変数は、関数に対して「ローカル」です。言い換えると、ローカル変数は特定の関数に所属しているということです。その関数が実行されている間のみアクティブとなります。ローカル変数が作成されるのは、関数の実行が開始された時であり、破棄されるのは、関数の実行が終了した時です。他の関数において使用することはできず、他のオブジェクトからアクセスすることもできません。

変数の宣言


変数の宣言をすることによって、新たな変数が作成され、クラスや構造体、関数の内部で使用できるようになります。変数の宣言は、次のように構成されています。まず、 var または local キーワードが置かれ、その次にオプションで 指定子 が置かれ、さらに、宣言する変数の型、変数に付ける名前が続きます。

var Type Name;
...
local Type Name;

UnrealScript で変数の宣言が行われる場所は、2 通りあります。インスタンス変数の宣言は、クラス宣言の直後 (あるいは構造体宣言の内部) で、あらゆる関数やステートが宣言される前に置かれます。ローカル変数の宣言は、関数の宣言の直後に、他のあらゆるコードの記述に先駆けて、関数本体の内部に置かれます。インスタンス変数は、 var キーワードを使用して宣言されます。ローカル変数は、 local キーワードを使用して宣言されます。

次は、UnrealScript におけるインスタンス変数の宣言例です。

class MyClass extends Actor;


// All istance variables must be declared before
// any functions or states are declared
var int A;			// Declare an integer variable named "A".
var byte Table[64];		// Declare a static array of 64 bytes named "Table".
var string PlayerName;		// Declare a string variable named "PlayerName".
var actor Other;		// Declare a variable which can be assigned a reference to an Actor instance.
var() float MaxTargetDist;	// Declare a float variable named "MaxTargetDist" and allow its value to be modified from an UnrealEd property window.

struct RangeVector
{
	var Vector Min;		// Declare a vector variable named "Min" within the struct.
	var Vector Max;		// Declare a vector variable named "Max" within the struct.
};

var RangeVector Bounds;		// Declare a RangeVector variable named "Bounds".

function foo
{
	...
}

var int B;			// This will cause an error

次は、ローカル変数の宣言例です。

function int Foo()
{
	// All local variables must be declared before
	// any other code in the function body
	local int Count;
	local float Seconds;

	Count = 1;

	// Declaring a local variable here would cause an error
	local float Minutes;

	return Count;
}

変数の指定子

変数の振る舞いをさらに詳細に記述するための付加的な指定子 (例 : const ) を変数に含めることができます。汎用プログラミング言語では見かけないような、非常に多くの指定子が提供されています。指定子の役割は主に、ゲーム固有のコンセプトや環境固有のコンセプトを UnrealScript によってネイティブにサポートされるようにすることにあります。

config
この変数は設定可能となります。現在の値を ini ファイルに保存し、変数作成時にそれをロードすることができます。 default properties において値を指定することはできません。暗黙的に const となります。
globalconfig
サブクラスでオーバーライドされないという点を除いて、config と同じ機能をもちます。default properties において値を指定することはできません。暗黙的に const となります。
localized
この変数の値によって、ローカライズされた値が定義されます。ほとんどの場合、文字列に使用されます。暗黙的に const となります。詳細については、 Localization Reference (ローカライズのためのリファレンス) および 「Unreal」の文字列 のページを参照してください。
const
変数の中身を定数として扱います。UnrealScript では、const 変数の値を読むことはできますが、書き込みはできません。const が使用されるのは、エンジンによって更新されなければならない変数、および、UnrealScript から安全に更新できない変数に対してのみです。この例としては、アクタの Location ( MoveActor 関数を呼び出すことによってのみ設定可能) があげられます。
private
変数が private になり、同クラスのスクリプトからのみアクセスできるようになります。ほかのクラス (サブクラスを含む) は、アクセスできません。
protected
この変数は同クラスとそのサブクラスからのみアクセスできます。ほかのクラスからはアクセスできません。
repnotify
複製によってこのプロパティの値を受け取った場合、アクタに通知されます ( ReplicatedEvent 関数によって)。
deprecated (非推奨)
この変数は近い将来削除され、エディタ内からアクセスできなくなることを示します。deprecated プロパティはロードされますが、保存されません。
instanced
オブジェクトのプロパティ専用です。このクラスのインスタンスが作成されると、デフォルトでこの変数に割り当てられているオブジェクトのユニークなコピーが与えられます。クラスの default properties で定義されるサブオブジェクトのインスタンス化に使用されます。
databinding
このプロパティは、データストアシステムによって操作されます。
editoronly
このプロパティの値は、UnrealEd またはコマンドレットを実行している場合にのみロードされます。ゲーム中は、このプロパティの値が破棄されます。
notforconsole
このプロパティの値は、PC で実行している場合にのみロードされます。コンソール上では、このプロパティの値が破棄されます。

editconst
エディタ。この変数は、UnrealEd 内に表示することができますが、編集することはできません。editconst の変数は、暗黙的に const には なりません
editfixedsize
エディタ。動的配列にのみ有効です。これによって、ユーザーが UnrealEd プロパティウィンドウを使用して配列の長さを変更してしまうことを防ぐことができます。
editinline
エディタ。この変数によって参照されるオブジェクトのプロパティを、UnrealEd のプロパティ インスペクタ内で編集できるようになります。(オブジェクト参照の配列を含むオブジェクト参照にのみ有効です)。
editinlineuse
エディタ。 editinline に関連づけられた動作に加えて、エディタ内において、このオブジェクト参照の横に [Use] (使用) ボタンが追加されます。
noclear
エディタ。このオブジェクト参照がエディタから None にセットされることを防ぎます。
interp
エディタ。Matinee 内の Float Property Track ( float 型プロパティ トラック) または Vector Property Track ( vector 型プロパティ トラック) によって、時間経過にともない値を変更できることを示します。
input
高度。変数を Unreal の入力システムにアクセスできるようにします。これによって、入力 (例 : ボタン押下、ジョイスティック動作) を変数に直接マッピングすることができるようになります。byte 型および float 型の変数のみ関係します。
transient
高度。この変数が一時的な使用のためのものであり、オブジェクトの永続的なステートの一部ではないことを宣言します。Transient 変数は、ディスクに保存されません。オブジェクトがロードされる時、変数は、その変数のための、クラスのデフォルト値に初期化されます。
duplicatetransient
高度。オブジェクトのバイナリ複製を作成する際に ( StaticDuplicateObject によって)、変数の値がクラスのデフォルト値にリセットされることを示します。
noimport
高度。T3D テキストがインポートされる際、この変数がスキップされることを示します。換言すれば、オブジェクトをインポート、コピー、ペーストする場合、この変数の値が新しいオブジェクトのインスタンスに移されないということになります。
native
高度。変数が、UnrealScript ではなく C++ コードによってロードされ保存されることを宣言します。
export
高度。オブジェクトプロパティ (またはオブジェクトの配列) にのみ有効です。オブジェクトがコピーされる (コピー / ペーストのために) か、T3D にエクスポートされる場合、オブジェクト参照そのものを出力するのではなく、このプロパティに割り当てられたオブジェクトが、サブオブジェクトのブロックとしてまるごとエクスポートされることを示します。
noexport
高度。native クラスにのみ有効です。この変数は、自動生成されたクラス宣言に含まれません。
nontransactional
高度。この変数値の変更が、エディタの undo (元に戻す) / redo (やり直す) の履歴に含まれないことを示します。
pointer{type}
高度。この変数は、 type へのポインタです。 ( type はオプションです)。構文は次のようになります。pointer 変数名{type}
init
高度。このプロパティは、FStringNoInit や TArrayNoInit としてではなく、FString または TArray としてヘッダ ファイルにエクスポートされます。native クラスで宣言された動的配列と文字列にのみ有効です。オブジェクトが作成される際にデフォルト値が消去されるため、Init プロパティにデフォルト値が割り当てられません。( UnrealScript の文字列 および native の文字列 のページを参照してください)。
repretry
高度。構造体のプロパティにのみ有効です。完全な送信に失敗した場合に、このプロパティの複製をリトライします。(例 : ネットワークによってシリアライズするのにまだ利用可能ではないオブジェクト参照)。単純な参照の場合には、この動作がデフォルトになっていますが、構造体の場合には、帯域幅のコストがかかるので望ましいことではありません。そのため、このフラグが指定されていない場合は、無効になっています。
allowabstract
高度。クラス参照にのみ有効です。abstract クラスを、エディタ内でこの変数に代入することができるようになります。

out
この指定子は関数パラメータにのみ有効です。詳細については、 関数のパラメータ指定子 のページを参照してください。
coerce
この指定子は関数パラメータにのみ有効です。詳細については、 関数のパラメータ指定子 のページを参照してください。
optional
この指定子は関数パラメータにのみ有効です。詳細については、 関数のパラメータ指定子 のページを参照してください。
skip
この指定子は演算子関数パラメータにのみ有効です。 && や || のような二項論理演算子のためにのみ使用されます。小規模なコードをストリームに入れるようにコンパイラに命じることによって、論理計算が第 1 の引数だけで完全に決定することができる場合に、第 2 の引数がスキップされる (評価されない) ようにすることができます。

これによって、次のような式で C のような動作が保証されます。

   if( ++a==10 && ++b==10 )
   

上記では、最初の式が失敗すると、++b がスキップされます。

メタデータ

変数は、メタデータという形態の付加的情報をもつことができます。このメタデータは、変数単位で指定します。メタデータの目的は、エンジンまたはエディタが使用する拡張機能を提供することです。特に、変数の表示名や、ツールチップ、最小最大値を指定するために使用することができます。

メタデータを変数にリンクさせるには、変数の宣言にメタデータを追加します。その場所は、変数名の後で、宣言を完結させるセミコロンの前に置きます。メタデータを指定するには、 Tag=Value という一連のペアを、パイプ文字 (|) で区切って、山括弧 < > の中に入れます。

例 :

var float MyVar<DisplayName=My Float Variable|Tooltip=This is a float variable with additional metadata specified|UIMin=0.0|UIMax=10.0|ClampMin=0.0|ClampMax=5.0>;

UnrealScript において変数とともにメタデータを使用するための詳細については、 UnrealScript のメタデータ のページを参照してください。

デフォルトのプロパティ

UnrealScript においては、他のプログラミング言語のように、変数を宣言する時に変数のデフォルト値を指定することはできません。さらに、UnrealScript で作成されるクラスには、デフォルト値をセットすることができる「コンストラクタ」関数という概念がありません。 それらの代わりに、UnrealScript では、 defaultproperties ブロックが、クラスを定義しているスクリプトの最後に追加されることによって、クラス内で宣言されたインスタンス変数のデフォルト値を指定することができます。通常のコードはこのブロックによって実行されず、UnrealScript の他の部分で使用されている構文とは若干異なる規則が適用されます。

例 :

defaultproperties
{
   IntVar=3
   FloatVar=2.5
   StringVar="This is a string"
   ArrayVar(0)=2
   ArrayVar(1)=4
   ArrayVar(2)=7
   ArrayVar(3)=1
}

UnrealScript において変数のデフォルト値を指定する方法、ならびに、さまざまな型のデータに使用される構文に関する詳細については、 UnrealScript のデフォルトプロパティ のページを参照してください。

変数の型


UnrealScript には、ビルトインされているデータ型が多数含まれています。これらの型は、変数を宣言する時に使用されます。変数の型によって、変数が保持できるデータの種類が決まります。かなり単純な型もあれば、理解して使用するのに複雑な型もあります。

基本データ型

以下は、他の言語でもよく使用され、UnrealScript でサポートされている基本的な変数データ型のリストです。

byte
0 から 255 までのシングルバイト値です。
int
32 ビットの整数値です。
bool
ブール値です。 true または false のいずれかの値を取ります。
float
32 ビットの浮動小数点数です。
string
文字列です。( 「Unreal」の文字列 のページを参照してください)。
constant (定数)
値を変えることができない変数です。
enumeration (列挙型変数)
あらかじめ定義された、名前の付けられた整数値の 1 つを取ることができる変数です。たとえば、Actor のスクリプトで定義された列挙型 ELightType は、動的ライトを表し、 LT_NoneLT_PulseLT_Strobe などのような値を取ります。

集合体データ型

array<Type> (配列)
の可変長配列です。
struct (構造体)
C 言語の構造体と同じように、 UnrealScript の構造体によって、サブ変数を内包する新しい変数型を作成することができます。たとえば、よく使用される構造体には 2 つあります。1 つは vector (ベクター) です。これは、X、Y、Z の成分から構成されています。もう 1 つは、 rotator (ローテータ) です。これは、ピッチ、ヨー、ロールの成分から構成されています。(詳細については、 構造体 のセクションを参照してください)。

Unreal 型

Name
「Unreal」内のアイテムを指す名前です。(たとえば、関数、ステート、クラスなどの名前)。name 型は、インデックスとして、グローバル名前テーブルに格納されます。name 型は、最大 64 文字までのシンプルな文字列に対応しています。name 型は、一度作成されると不変であるという点で、文字列と異なります (詳細については、 UnrealScript の文字列 のページを参照してください)。
オブジェクトおよびアクタへの参照
ワールド内にある他のオブジェクトやアクタを参照する変数です。たとえば、Pawn クラスは、 Enemy (敵) アクタへの参照を持っています。(この参照は、ポーンがどのアクタを攻撃すれば良いかということを指定するものです)。オブジェクトとアクタへの参照は、これによって他のアクタの変数や関数へのアクセスが可能になるため、非常に便利なツールです。たとえば、 Enemy.TakeDamage(123) などのように書くことによって、敵の TakeDamage (被ダメージ) 関数を呼び出すことができます。 (その結果、敵はダメージを受けます)。オブジェクトへの参照にも None (C 言語の NULL ポインタに相当します) という特別な値が含まれています。この値の意味は、「この変数はどのオブジェクトも参照していません」ということです。
Delegate (デリゲート)
UnrealScript の関数への参照を保持します。

編集可能性


UnrealScript では、インスタンス変数を editable (編集可能) にすることができます。これによって、「Unreal」エディタ内で変数の値を編集できるようになります。このメカニズムは、「Unreal」エディタ内の Actor Properties (アクタプロパティ) ダイアログのすべてのコンテンツに及びます。したがって、ダイアログに表示されるのは、すべて editable (編集可能) として宣言された UnrealScript 変数なのです。

editable (編集可能) な変数を宣言するための構文は、次のようになります。

var() int MyInteger; // Declare an editable integer in the default
                     // category.

var(MyCategory) bool MyBool; // Declare an editable integer in
                             // "MyCategory".

また、変数を editconst として宣言することもできます。この意味は、変数が「Unreal」エディタに表示されるものの、それは編集 できない ということです。なお、これによって変数が変更できなくなるのはエディタからであって、スクリプトでは編集できます。実際は const でありながらもエディタで表示できる変数が必要な場合は、 const editconst として宣言します。

// MyBool is visible but not editable in UnrealEd
var(MyCategory) editconst bool MyBool;

// MyBool is visible but not editable in UnrealEd and
// not changeable in script
var(MyCategory) const editconst bool MyBool;

// MyBool is visible and can be set in UnrealEd but
// not changeable in script
var(MyCategory) const bool MyBool;

配列


配列は、以下の構文を使用して宣言します。

var int MyArray[20]; // Declares an array of 20 ints.

UnrealScript では、1 次元の配列しかサポートされていませんが、行 / 列の計算を行うことによって、多次元配列をシミュレートすることができます。動的配列に関する詳細については、以下の 言語の高度な機能 のセクションを参照してください。

動的配列

上記で取り上げた配列は、静的な配列です。静的な配列とは、コンパイル時にサイズ (配列内の要素数) がセットされ、その後変更できない配列のことを言います。動的な配列と静的な配列には、以下のような共通点があります。

  • 一定のシーク時間 - 配列の要素数にかかわらず、配列の特定要素にアクセスするためにコードが費やす時間は一定です。
  • 要素の型に制限がない - 整数、ベクトル、アクタなど、どのようなタイプの配列でも作ることができます。(ブール型は例外であり、動的配列にのみ有効です)。
  • アクセスの動作 - 配列に入るインデックスをもつ要素であれば、どれにでもアクセスすることができます。逆に、配列のサイズを超えるインデックスの要素にアクセスしようとすると、accessed none (空の参照にアクセスした) がスローされます。

動的配列は、変化するニーズに応えるため、静的配列の機能に加えて、実行時に配列要素数を変更できる機能を持ち合わせます。動的配列を使用するためには、何点か知るべきことがあります。

1 つ目は、変数の宣言についてです。動的配列を宣言する方法は、その他の UnrealScript の変数を宣言する方法とよく似ています。(すなわち、var/local 配列名 とします)。動的配列の場合、型を指定するには array キーワードの後ろに配列型を山括弧 < > の中に入れて置きます。配列型にも山括弧が含まれている場合 (例 : class<Actor> )、型の閉じ括弧と配列ラッパーの閉じ括弧の間にスペースを入れる必要があります。そうしなければ、コンパイラが 2 つの閉じ山括弧を、 >> 演算子として処理してしまいます。以下は宣言の例です。
IntList という名前の int 型の動的配列を宣言してみます。

var array<int> IntList;

Players という名前の class<PlayerController> 型の動的配列を宣言してみます。

var array<class<PlayerController> > Players;

スクリプトが開始すると、IntList は 0 要素から開始されます。動的配列にサポートされているメソッドによって、配列に要素を追加したり、要素を取り出したり、配列の長さを任意に増減させたりすることができます。これらのメソッドを呼び出すための構文は、(上記 IntList の例を使用すると) 次のようになります。 IntList.MethodName() 以下の動的配列のメソッドが利用できます。

  • Add(int Count): Count の分だけ、配列のサイズを大きくします。(FArray::AddZeroed() と同じです)。
  • Insert(int Index, int Count): Index は、要素が挿入される配列のインデックスであり、 Count は挿入する要素の個数です。挿入場所にあった既存の要素は、後方に順送りされ、新たな要素が作成されて、指定された場所に挿入されます。たとえば、インデックス 3 のところに 5 個の要素を挿入すると、配列内のインデックス 3 以降にあったすべての要素が (インデックスの値で) 5 つ分それぞれ後にずれていきます。挿入前にインデックス 3 に位置していた要素は、インデックス 8 に位置することになり、要素 4 は要素 9 となります。新しく追加された要素は、すべてデフォルト値に初期化されます。( structdefaultproperties がある構造体を除いて、すべての型のデフォルト値は、ゼロ/null です)。
  • Remove(int Index, int Count): Index は、要素の削除が開始される配列インデックスであり、 Count は削除される要素の数です。このメソッドによって、配列内にある有効なインデックスから開始して、配列要素をまとめて配列から削除することができます。なお、削除範囲よりも大きい値のインデックスについては、インデックス値が変更されます。動的配列にインデックス値を保存する場合は、このことを忘れないでください。
  • AddItem(Item): 配列の最後に Item を追加し、配列のサイズを 1 つ分大きくします。
  • RemoveItem(Item): 線形探索を使用して、 Item のインスタンスすべてを削除します。
  • InsertItem(int Index, Item): Index の配列に Item を挿入し、配列のサイズを 1 つ大きくします。
  • Find(...) - 配列内で要素のインデックスを検索します。Find には 2 種類あります。1 つは、一致する要素の値全体を検索する標準的な検索で、もう 1 つは、構造体が含んでいる単一のプロパティの値に基づいて、一致する構造体を検索する特別な検索です。
    • Find(Value): Value は、検索対象の値です。指定された値に一致する要素が配列内で見つかったら、その最初の要素のインデックスを返します。その値が配列内で見つからなかった場合は、-1 を返します。 Value の部分は、有効な表現式であれば何を使用してもかまいません。
    • Find(PropertyName, Value): PropertyName は、検索対象となる構造体が含んでいるプロパティ名です (Name 型でなければなりません)。 Value は、検索する値です。 PropertyName というプロパティのために指定された値と一致する値をもつ構造体が見つかったら、その最初の構造体のインデックスを返します。その値が見つからなかった場合は、-1 を返します。 Value の部分は、有効な表現式であれば何であってもかまいません。
  • Sort(SortDelegate) - SortDelegate を使用して、インプレースで配列の内容をソートします。 SortDelegate のシグニチャは、次と一致しなければなりません。
    • delegate int ExampleSort(ArrayType A, ArrayType B) { return A < B ? -1 : 0; } // 負の値は、アイテムがスワップされなければならないことを示します。

Length 変数

動的配列には、 Length という変数があります。これは、動的配列の現在のサイズ (要素数)を示します。上記例の配列を用いて Length にアクセスするには、 IntList.Length とします。Length 変数は読み取るだけでなく、直接、値を設定することができます。これによって、配列内の要素数を変更することができます。直接 Length 変数を変更すると、配列サイズの変化はすべて配列の「最後」で生じます。たとえば 、IntList.Length = 5 とセットし、さらに IntList.Length = 10 とセットすると、余分な 5 個の要素が配列の最後に追加され、元々あった 5 つの要素とその値はそのまま残ります。Length を小さくした場合も、要素の最後から削除されます。なお、Insert() による挿入、または、Length の増加によって要素を配列に加えると、要素はその変数型のデフォルト値に初期化されます。(整数型は 0、クラス参照型は None など)。また、配列の現在の Length 値よりも大きい要素のインデックスをセットすることによって、動的配列のサイズを大きくすることができることを、知っておくべきでしょう。これによって、Length により大きな値をセットした場合と同じように、配列を拡張することができます。

OldLength = Array.length 
Array.Length = OldLength + 1
Array[OldLength] = NewValue

Array[Array.Length] = NewValue 

Array.AddItem(NewValue) 

上記はすべて、同一の操作を行なっていることになります。

ただし、配列のサイズを増加させることと同時に、そのメンバーにアクセスすることはできません。

Array[Array.length].myStructVariable = newVal

というようにはできないことになります。

注意事項 - 動的配列の Length メンバーは、決して ++ 、- -、+= 、-= を使ってインクリメント / デクリメントしないでください。また、Length を out パラメータ (関数はこの値を変えることができる) として関数に渡さないでください。これらを行うと、Length の正確性が失われるため、メモリリークが生じ、クラッシュします。 = 演算子を使って Length をセットする場合にのみ (また、Length よりも大きいインデックスの要素をセットする場合にのみ)、動的配列の実際の長さを適切に変更することができます。

注意 : array<bool> という型はサポートされていません!

最後の注意事項 - 動的配列は、複製 されません 。この問題に対処するには、関数を作成します。この関数は、複製を実行し、2 つの引数、および、動的配列に入れるインデックス、および、そこに保持する値をもたなければなりません。ただし、要素が、クライアントとサーバ上において同じティックスペースに入らなくなるという結果を考慮する必要があるでしょう。

動的配列をイテレートする

シンプルなイテレーションを可能にする foreach コマンドが、動的配列でサポートされました。基本的な構文は、次のようになります。

foreach ArrayVariable(out ArrayItem, optional out ItemIndex)
{
   ...
}

ArrayItem は、配列の要素と同じ型でなければなりません。各イテレーションによって、インデックスがインクリメントされ、プロパティが指定されると、アイテムおよびインデックスが書き出されます。

function IterateThroughArray(array SomeArray)
{
    local string ArrayItem;
    local int Index;
    foreach SomeArray(ArrayItem)
    {
       `log("Array iterator test #1:"@ArrayItem);
    }
    foreach SomeArray(ArrayItem,Index)
    {
        `log("Array iterator test #2:"@ArrayItem@Index);
    }
}

構造体


UnrealScript の構造体を使用することによって、大量の変数を、構造体と呼ばれる新たな種類のスーパー変数に詰め込むことができます。 UnrealScript の構造体は、変数や配列、他の構造体を含むことができるという点で、C 言語の構造体によく似ています。ただし、UnrealScript の構造体は関数を含むことができません。

UnrealScript で構造体を使用することによって生じるパフォーマンスへの影響に関する詳細については、 UnrealScript の構造体 のページを参照してください。

構造体の定義

構造体変数を宣言するには、まず、使用する構造体を定義する必要があります。構造体を定義するには、 struct キーワードの後に、その構造体に付ける名前を置きます。次に、波括弧 { } の中で、構造体に含まれる変数を宣言します。この時使用する構文は、他のインスタンス変数を宣言する場合と同じ構文です。閉じ波括弧の後にセミコロンを付けます。

次の例では、ベクターのための構造体を定義しています。

// A point or direction vector in 3D space.
struct Vector
{
	var float X;
	var float Y;
	var float Z;
};

構造体の中に含まれる変数のためのデフォルト値を指定することができます。そのためには、構造体の定義の内部に、 structdefaultproperties のブロックを追加します。たとえば、 Vector 構造体に含まれている変数がそれぞれ 1.0 という値から始まるように予め指定しておくには、次のように構造体を定義します。

// A point or direction vector in 3D space.
struct Vector
{
	var float X;
	var float Y;
	var float Z;

	structdefaultproperties
	{
		X=1.0
		Y=1.0
		Z=1.0
	}
};

構造体メンバーのデフォルトプロパティに関する詳細については、 UnrealScript のデフォルトプロパティ のページにある 構造体のデフォルト? のセクションを参照してください。

構造体の指定子

構造体には、指定子がいくつか備わっています。この指定子は、構造体のインスタンスすべてに影響を及ぼします。指定子が定義の中で置かれる位置は、 struct キーワードと構造体名の間です。

atomic
当該構造体が常に、単一のユニットとしてシリアライズされることを示します。当該構造体にあるプロパティのいずれかがデフォルト値と異なる場合は、構造体のすべての要素がシリアライズされます。
atomicwhencooked
クックされたパッケージデータを扱っている場合にのみ、atomic フラグを適用します。
immutable
バイナリシリアライゼーションが当該構造体によって使用されることを示します。(これによって、ディスクスペースが削減され、シリアライズのパフォーマンスが向上します)。パッケージのバージョンをインクリメントせずに、当該構造体からメンバーを追加 / 削除することは危険です。
immutablewhencooked
クックされたパッケージデータを扱う場合にのみ、immutable フラグを適用します。
strictconfig
構造体のプロパティに config/globalconfig が付いている場合に、この構造体内で config/globalconfig とマークされたプロパティのみが.ini ファイルから読み込まれることを示します。(このフラグがなければ、構造体に含まれているすべてのプロパティがコンフィギュレーション可能となります)。

構造体変数を宣言する

構造体の宣言が済むと、その構造体型の固有の変数を、次のようにして宣言することができます。

// Declare a bunch of variables of type Vector.
var Vector Position;
var Vector Destination;

構造体の変数を使用する

構造体の成分にアクセスするには、次のようなコードを使用します。

function MyFunction()
{
	Local Vector A, B, C;

	// Add some vectors.
	C = A + B;

	// Add just the x components of the vectors.
	C.X = A.X + B.X;

	// Pass vector C to a function.
	SomeFunction( C );

	// Pass certain vector components to a function.
	OtherFunction( A.X, C.Z );
}

他の変数で使ってできることはすべて、構造体変数を使って行うことができます。すなわち、構造体変数に変数を代入することができ、構造体変数を関数に渡すことができ、構造体変数の構成要素にアクセスすることができます。

Object クラスには構造体がいくつか定義されており、「Unreal」の至るところで使用されています。これらの 構造体は、スクリプトの基本的な構成ブロックであるため、その操作法について慣れておく必要があります。

Vector
X、Y、Z 成分をもつ、空間内の一意な 3D 点またはベクターです。
Plane
3D 空間を内の一意な平面を定義します。平面は X、Y、Z 成分 (正規化されていることが前提となります) および W 成分によって定義されます。W 成分は、平面の法線に平行である、原点から平面までの距離 (平面から原点までの最短距離) を表します。
Rotator
一意な直交座標系を定義する回転です。回転には、Pitch (ピッチ)、Yaw (ヨー)、Role (ロール) の各成分が含まれます。
Coords
3D 空間内における任意の座標系です。
Color
RGB カラー値です。
Region
レベル内で一意な凸形領域を定義します。

列挙型変数


UnrealScript の列挙型変数は、多数のキーワードのうち「1 つ」を含むことができる変数を宣言する場合に便利です。たとえば、Actor クラスには列挙型変数の EPhysics が含まれています。この列挙型変数は、Unreal がアクタに適用すべき物理を表しています。この列挙型変数には、 PHYS_NonePHYS_WalkingPHYS_Falling などの既定値から、1 つを設定することができます。

列挙型変数は内部的に、byte 型変数として格納されます。UnrealScript の設計段階では、列挙が必要なものとは見なされていませんでした。しかし、アクタの物理モードが、たとえば 3 などではなく PHYS_Swimming などにセットされているほうが、コードを読む際はるかに理解しやすくなります。

次は、列挙型変数を宣言しているコード例です。

// Declare the EColor enumeration, with three values.
enum EColor
{
   CO_Red,
   CO_Green,
   CO_Blue
};

// Now, declare two variables of type EColor.
var EColor ShirtColor, HatColor;

// Alternatively, you can declare variables and
// enumerations together like this:
var enum EFruit
{
   FRUIT_Apple,
   FRUIT_Orange,
   FRUIT_Bannana
} FirstFruit, SecondFruit;

Epicでは、列挙型変数に入る値は、「Unreal」のソースコード内で、 LT_SteadyPHYS_Falling などのように宣言し、単に Steady や Falling とは宣言していません。これは、プログラミングのスタイルの問題であって、この言語の条件ではありません。

非限定の enum タグ (例 : FRUIT_Apple ) については、その列挙型変数が定義されたクラスとそのサブクラス内でしか UnrealScript に認識されません。クラス階層内のどこか他の場所で定義された列挙型変数のタグを参照する必要がある場合は、次のようにして、「限定」 (qualify) しなければなりません。

FRUIT_Apple         // If Unreal can't find this enum tag...
EFruit.FRUIT_Apple  // Then qualify it like this.

列挙型変数の値は、静的配列のサイズとして使用することができます。また、静的配列は、列挙型変数に含まれているアイテムの数に等しいサイズであると、宣言することができます。そのためには、宣言において、列挙型変数の型名を使います。次がその例です。

var int MyIntArray[EFruit];

定数


UnrealScript では、ほとんどすべてのデータ型について定数リテラル値を指定することができます。

  • 整数型定数と byte 型定数は、単純な数字で指定します。 (例 : 123 )。16 進数形式で整数定数またはバイト定数を指定しなければならない場合は、 0x123 のように指定します。
  • float 型定数は、小数で指定します。 (例 : 456.789 )。
  • 文字列定数は、ダブルクオーテーションマークで囲む必要があります。 (例 : "MyString" )。
  • name 型定数は、シングルクオーテーションマークで囲む必要があります。 (例 : 'MyName' )。
  • vector 型定数は、X、Y、Z 値を含みます。 (例 : vect(1.0,2.0,4.0) )。
  • rotator 型定数は、ピッチ、ヨー、ロール値を含みます。 (例 : Rot(0x8000,0x4000,0) )。
  • None 定数は、「オブジェクトが存在しない」(あるいは、「アクタが存在しない」) ことを意味します。
  • Self 定数は、「このオブジェクト」 (または「このアクタ」) を意味します。すなわち、スクリプトが実行されているオブジェクトのことになります。
  • 一般的なオブジェクト定数を指定するには、オブジェクト型に続けてシングルクオーテーションマークに囲まれたオブジェクト名を置きます。 (例 : texture'Default' )。
  • EnumCount は、列挙型変数に入っている要素数を示します。 (例 : ELightType.EnumCount )。
  • ArrayCount は、静的配列に入っている要素数を示します。 (例 : ArrayCount(Touching) )。

const キーワードを使用することによって、名前で参照できる定数を宣言することができます。例 :

const LargeNumber=123456;
const PI=3.14159;
const MyName="Tim";
const Northeast=Vect(1.0,1.0,0.0);

定数は、クラスまたは構造体の内部で定義することができます。

他のクラスで宣言された定数にアクセスするには、classname.constname 構文を使用します。たとえば、次のようになります。

class'Pawn'.const.LargeNumber

オブジェクト / アクタ参照変数


アクタまたはオブジェクトを参照する変数を宣言するには、次のようにします。

var actor A;	// An actor reference.
var pawn P;	// A reference to an actor in the Pawn class.
var texture T;	// A reference to a texture object.

上記例の変数 P は、Pawn クラスのアクタへの参照です。このような変数は、Pawn のサブクラスに属するあらゆるアクタを参照することができます。たとえば、P は Brute 、Skaarj 、Mantaを参照することができます。あらゆる種類の Pawn を参照することが可能です。ただし、P は、けっして Trigger アクタを参照することはできません。( Trigger は Pawn のサブクラスではないからです)。

アクタを参照する変数の便利な例として、Pawn クラス内にある Enemy 変数をあげることができます。(この Enemy 変数は、Pawn が攻撃しようとしているアクタを参照します)。

アクタを参照する変数があれば、そのアクタの変数にアクセスしたり、アクタの関数を呼び出したりすることができます。 例 :

// Declare two variables that refer to a pawns.
var pawn P, Q;

// Here is a function that makes use of P.
// It displays some information about P.
function MyFunction()
{
   // Set P's enemy to Q.
   P.Enemy = Q;

   // Tell P to play his running animation.
   P.PlayRunning();
}

アクタを参照する変数は、常に、有効なアクタ (当該レベル内に実際に存在するあらゆるアクタ) を参照するか、 None 値を持つかのどちらかです。None は、C/C++ の NULL ポインタに相当します。ただし、UnrealScript では、 None 参照を使用して、変数にアクセスしたり、関数を呼び出したりしても安全です。その結果は必ずゼロになるからです。

なお、オブジェクトまたはアクタへの参照は、別のアクタまたはオブジェクトを「指す」だけであって、別のアクタまたはオブジェクトを「含む」わけではありません。C 言語においてアクタへの参照に相当するのは、AActor クラス内にあるオブジェクトへのポインタです。(C 言語では、AActor* と書きます)。たとえば、ワールド内に Bob と Fred という、敵同士のモンスターが 2 匹いるとします。Bob の Enemy 変数は、Fred を「指し」、Fred の Enemy 変数は Bob を「指します」。

C 言語のポインタとは違い、UnrealScript のオブジェクト参照は安全で絶対確実です。存在しないオブジェクトや、無効なオブジェクトをオブジェクト参照が参照することはありえません。(特別な場合である None 値を除いて) UnrealScript では、アクタが破棄されると、そのアクタへの参照はすべて自動的に None にセットされます。

参照に関する詳細、ならびに、参照を使用してオブジェクト同士にコミュニケーションさせる方法に関する詳細については、 スクリプト間のコミュニケーション? のセクションをご覧ください。

クラス参照変数


「Unreal」では、アクタ、テクスチャ、サウンドがオブジェクトであるのと同様に、クラスもオブジェクトです。クラスオブジェクトは、class という名前のクラスに属しています。あるクラスに属しているアクタをスポーンできるようにするために、(コンパイル時にそれがどのクラスであるかを知らずに) クラスオブジェクトへの参照を保存しなければならない場合がよくあります。例 :

var() class C;
var actor A;
A = Spawn( C ); // Spawn an actor belonging to some arbitrary class C.

ここで、「クラス C 」の役割と、「クラスCに所属するオブジェクト O」(クラス C の「インスタンス」) の役割を混同しないようにしてください。かなり強引な比喩となりますが、クラスは、コショウ挽き器で、そのクラスのインスタンスは、コショウです。コショウ挽き器 (クラス) を使用して、コショウ (そのクラスのオブジェクト) を作成するためには、取っ手を回します ( Spawn 関数を呼びます)。ただし、コショウ挽き器 (クラス) は、コショウ (クラスに属しているオブジェクト) ではないので、食べようとしてはいけません!

クラスオブジェクトを参照する変数を宣言する際、 class<metaclass> という構文を使用することによって (オプション)、変数が参照できるクラスを、 metaclass 型のクラス (と、その子クラス) に限定することができます。たとえば、次のように宣言します。

var class ActorClass;

変数 ActorClass は、actor クラスを拡張したクラスに限って参照することができます。これは、コンパイル時の型チェックの改善に役立ちます。たとえば、Spawn 関数は、パラメータとしてクラスを取り (ただし、そのクラスが Actor のサブクラスである場合に限って意味を持ちます)、 class<classlimitor> 構文によって、コンパイラがその要件を実施します。

動的なオブジェクトのキャスト同様、次のようにして、クラスを動的にキャストすることができます。

// casts the result of SomeFunctionCall() a class of type Actor (or subclasses of Actor)
class( SomeFunctionCall() )

型キャスト


型キャストとは、ある値から他の値に変換するプロセスのことです。通常は、変換のターゲットである型の変数に、その値を代入する場合に行われます。ある型から他の型に値をキャストするのが役立つのは、単純なデータ型の場合だけではなく、オブジェクト参照などのような複雑な型の場合についても同様です。ただし、型キャストによってデータが失われる可能性があることも覚えておいてください。精度のレベルは、データの型によってさまざまに異なります。高い精度の型から低い精度の型に変換した場合は、余分な桁の精度が切り捨てられることになります。

型キャストの形態には、非明示的な形態と明示的な形態の 2 つがあります。

非明示的な型キャスト

変数データ型の中には、型同士が自動的に変換される機能が備わったものがあります。(通常は、 byteintfloat といった数値データ型がそれに該当します)。このような型キャストは、キャストする型を明示的に指定せずにデータ型を変換するため、非明示的な型キャストと呼ばれています。非明示的な型キャストが実行されるのは、ある型の変数の値を、他の型の変数に代入する場合です。

以下にその例をあげます。

var int IntVar;
var float FloatVar;

...

IntVar = 2;		// IntVar holds the value 2
FloatVar = 4.25;	// FLoatVar holds the value 4.25

...

IntVar = FloatVar;	// IntVar now holds the value 4

FloatVarIntVar の型は異なりますが、一方の変数の値を他方の変数に代入することが可能です。これは、互いに非明示的にキャストできる機能が int 型と float 型にサポートされているためです。

明示的な型キャスト

数値データ型が非明示的に変換されるのに対して、他の型は、変換のターゲットとなる型を明示的に指定しなければなりません。ただし、すべての型が明示的に他の型にキャストできるとは限りません。変換される型には、ターゲットの型に変換される機能がサポートされている必要があります。そうでなければ、コンパイラはエラーを投げます。

明示的に値をキャストするには、キャストする型を書き、その後にキャストする値を丸括弧でくくります。基本的な構文は、次のようになります。

TypeToCastTo(ValueToCast)

たとえば、 Vector 型変数を、 String 型として表示するとします。 Vector 型には、 String 型へ明示的にキャストする機能がサポートされているため、次のようにすることは完全に有効です。

var Vector Offset;
var String OffsetText;

...

Offset = vect(1.0, 2.5, 5.0);	//Offset now holds the values X=1.0, Y=2.5, Y=5.0
OffsetText = String(Offset);	//OffsetText now holds the value "1.0,2.5,5.0"

明示的なキャストがサポートされている型

String
String データでは、次の型への変換がサポートされています。
  • Byte, Int, Float - String に保持されている数字は、実際の数値に変換されます。 String の値に数字が含まれていない場合は、キャストの結果が、 0 または 0.0 (変換ターゲットの型に依存します) になります。
  • Bool - String の値を、 TRUE または FALSE のどちらかに変換します。 String"True""False" (大文字、小文字を区別します) のどちらかが含まれている場合は、テキストがそれに相当する Bool 値に直接変換されます。 それらの値がどちらもない場合は、 String の値がまず数値に変換され (上記で説明されているルールに従います)、さらに、それらが Bool 値に変換されます。その場合、値が 0 の場合は FALSE に、それ以外の値は TRUE に変換されます。
  • Vector, Rotator - テキスト形式の Vector あるいは Rotation を保持している String (3 個の数値がコンマで区切られた形式。例 : “0.5,23.64,18.43”) を、指定されたターゲットのデータ型に変換します。 Vector の変換については、 String にある数値が、精度が小数点以下第 2 位までの Float 値に変換されます。 Rotator の変換については、 String にある数値が丸められ (小数部分がすべて切りてられ)、 Int 値に変換されます。
Bool
Bool データ型では、次の型への変換がサポートされています。
  • String - BoolTRUE 値または FALSE 値を、 String 値の "True" または "False" に変換します。
  • Byte, Int, Float - BoolTRUE 値または FALSE 値を、それぞれ、数値の 1 または 0 に変換します。
Byte, Int, Float, Vector, Rotator
これらの数値データ型では、次の型への変換がサポートされています。
  • String - 数値 (複数も) をテキスト形式に変換します。 Vector または Rotator の場合のテキスト形態は、3 個の数値 ( X 、==Y== 、 Z または PitchYawRoll ) がコンマで区切られます。
  • Bool - 数値 (複数も) を、 Bool 値の TRUE または FALSE に変換します。非ゼロの値はすべて TRUE に変換し、ゼロの値は FALSE に変換します。 Vector または Rotator の場合は、各成分の値がゼロの時に FALSE に変換します。非ゼロの値がある場合は、 TRUE に変換します。
Name
Name データ型では、次の型への変換がサポートされています。
  • String - Name のテキスト値を、 STRING のテキスト値に変換します。
Vector
Vector データ型では、次の型への変換がサポートされています。
  • Rotator - ワールドの原点から Vector の座標によって指定された位置への方向を、その方向に対応する RotatorPitch 値と Yaw 値に変換します。 Roll 値は、常に 0 になります。
Rotator
Rotator データ型では、次の型への変換がサポートされています。
  • Vector - RotatorPitch 値、 Yaw 値、 Roll 値を、原点から発して回転の方向を指す Vector の座標に変換します。
Object Reference
オブジェクト参照 型では、次の型への変換がサポートされています。
  • Int - オブジェクト参照 を一意の Int 値に変換します。
  • Bool - 変数が有効な参照を保持している場合は、 オブジェクト参照FALSE に変換します。保持している値が None の場合は、 FALSE に変換します。
  • String - オブジェクト参照 を、テキスト形式 (すなわち参照されている オブジェクト参照 または アクタName プロパティ )に変換します ( NameString にキャストした後に)。参照されている オブジェクト がない場合は、 None に変換します。
  • オブジェクト参照 - 2 つのクラスに関連性がある場合は、 オブジェクト参照 は、一方のクラスから他方のクラスに変換できます。この種のキャストに関する詳細については、 オブジェクト参照を変換する のセクションをご覧ください。

オブジェクト参照を変換する

上記の変換機能は、単純なデータ型同士の変換でしたが、UnrealScript では、アクタおよびオブジェクトの参照も、同じようにさまざまな型に変換することができます。たとえば、すべてのアクタには、他のアクタを参照する Target という変数があります。仮に、スクリプトを書いていて、ある Target が Pawn アクタクラスに属しているか否かを調べて、Pawn である時にのみ意味があるような特別な処理をこの Target に行う必要がある場合、(たとえば) この Pawn の関数の 1 つを呼び出す必要が出てきます。アクタのキャスト演算子によってこのことが可能になります。次はその例です。

var actor Target;
//...

function TestActorConversions()
{
	local Pawn P;

	// Cast Target to Pawn and assign the result to P.  If Target is not a Pawn (or subclass of Pawn), then the value assigned to P will be None.
	P = Pawn(Target);
	if( P != None )
	{
		// Target is a pawn, so set its Enemy to Self.
		P.Enemy = Self;
   	}
   	else
   	{
	   	// Target is not a pawn.
   	}
}

アクタの変換を実行するには、クラス名を書き、その後に変換したいアクタの式を丸括弧でくくります。このような変換は、適切な変換であるかによって、成功するか失敗するかのどちらかです。上記の例について考えてみると、Target が 、Pawn ではなく Trigger オブジェクトを参照している場合は、Pawn (Target) の式によって None が返されます。Trigger は Pawn によって変換できないからです。しかし、Target が Brute オブジェクトを参照している場合は、変換が成功して Brute を返します。Brute が Pawn のサブクラスだからです。

このように、変換には 2 つの目的があります。1 つは、変換を利用して、ある特定のアクタ参照が特定のクラスに属しているか否かを調べることです。もう 1 つは、変換を利用してあるアクタ参照を、あるクラスからより固有なクラスに変換することです。なお、これらの変換は、変換しているアクタにはまったく影響を及ぼしません。単に、アクタ参照をより固有な型のように UnrealScript が扱うことができ、より派生が進んだクラスで宣言されたプロパティとメソッドにユーザーがアクセスできるようになるだけです。

変換のもう 1 つの例として、Inventory (インベントリ) のためのスクリプトをあげることができます。各 Inventory アクタは、Pawn によって所有 (own) されています。ただし、その Owner 変数は、どのような Actor も参照することができます (なぜなら、Actor.Owner が Actor 型の変数だからです)。したがって、Inventory のためのコードの一般的なテーマは、(たとえば) Owner を Pawn にキャストするということになります。

// Called by engine when destroyed.
function Destroyed()
{
	// Remove from owner's inventory.
	if( Pawn(Owner)!=None )
    	Pawn(Owner).DeleteInventory( Self );
}