UDN
Search public documentation:

KismetExamplesJP
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 ホーム > Kismet ビジュアルスクリプト処理 > Kismet の具体例
UE3 ホーム > シネマティックアーティスト > Kismet の具体例

Kismet の具体例


概要


Kismet とは、強力なビジュアルスクリプト処理システムです。これを使用することによって、レベルデザイナーは、ダイナミックで魅力的なゲームプレイをレベルに比較的簡単に追加することができます。このドキュメントで解説するコンセプトとテクニックは、 アクション条件変数イベント と組み合わせることによって、新しく革新的なゲームプレイイベントを作成するのに役立つものです。

Kismet の使用方法に関する詳細は、 Kismet ユーザーガイド および Kismet のリファレンス のページを参照してください。

コンセプト


このセクションで解説しているさまざまなコンセプトやテクニックは、重要なものです。一般的な関数を実行する場合や Kismet のシーケンスの効率を向上させる場合に使用することができます。

シーケンス

Kismet は、レベル内の特定のイベントと条件に反応して一連のアクションを実行します。シリーズ (Kismet において一続きになっているもの) または関連するシリーズの集まりは、 シーケンス (sequence) として見なされます。各レベル (パーシスタントまたはストリーミング) は、デフォルトで、基本シーケンスをもっています。これらシーケンスは階層を形成し、たいていは、独立しています。ただし、ストリーミングレベルのシーケンスは、親のパーシスタントレベルのシーケンスにある要素にアクセスすることができます。

ex_sequence_hier.jpg

各レベルがもつ基本シーケンスの他に、アクションおよびイベント、条件、変数の集まりを、新たなシーケンスまたは サブシーケンス に自由に置くことができます。

ex_subsequence.jpg

この場合も、階層が形成され、階層を逆上ってアクセスすることはできますが、横にはアクセスすることができません。すなわち、他のシーケンス内にある変数やそれに類するものにアクセスするには、それらが階層の直接上に位置していなければならないということになります。仮に、2 つのシーケンスが同一の親シーケンスをもつとして、これら 2 つのシーケンスは、親シーケンス (またはその親) に含まれている変数にアクセスできますが、2 つのシーケンスが、お互いの中に含まれている変数にアクセスすることはできません。

シーケンスは、Kismet を編成する際に非常に優れた方法です。これから作成する新たなシーケンスには、任意の数の入力あるいは出力、変数のリンクをもたせることができます (Sequence Activated (シーケンスのアクティベート化) イベント、および、 Finish Sequence (シーケンスの完了) アクション、 手続き主義 (Proceduralism)

手順主義 (Proceduralism) という語は、Kismet で使用される場合、汎用的に作成されたシーケンスを利用することを意味します。 (シーケンスとは、この場合、アクションのシリーズ、または、完全なサブシーケンスのどちらかです。また、シーケンスは、入力に接続される Remote Events (リモートイベント) 、ならびに、変数リンクに接続される Global Variables (グローバル変数) を使用し、さらに、それら変数に対して (あるいは、それら変数を使用して) 何らかのアクションを実行します)。本質的には、標準的なプログラミングに見られる関数やプロシージャに類似した機能を作成するために、シーケンスという考え方を取っているということになります。プロシージャシーケンスを実行するためには、単に、 Global Variables の値 (複数も) をセットし、さらに、 Activate Remote Event アクションを使用して、関連する Remote Event をトリガーすることにより、シーケンスをアクティベートします。

実例を使ってこの考え方を説明するために、あるアクタを他のアクタの位置と回転に素早くセットしてアタッチさせる場合のことを考えてみます。これを実現する一般的なシーケンスは、次のようになります。

ex_proc_normal.jpg

さて、ここで、これと同じアクションのシリーズを何回もさまざまなアクタで実行する場合のことを考えてみます。このシーケンスが必要となるたびに複製することは、明らかに、大変なことであり、Kismet のワークスペースも乱雑になってしまいます。

ex_proc_clutter.jpg

これとは対照的に、プロシージャバージョンのシーケンスは、次のようになります。

ex_proc_procedural.jpg

プロシージャ的にすることによって、単一のプロシージャシーケンスを、必要となるたびに再利用することができます。やるべきことは、変数をセットし、イベントをアクティベートするだけです。

このテクニックを使用することの真の意義は、シーケンスに変更を加える場合に顕著となります。変更しなければならないシーケンスを探しまわり、複数のコピーを取る必要はなく、単一の場所にある単一のシーケンスを変更すれば済むのです。

イベント

イベント (event) は、Kismet の基礎となるものです。イベントは、事前に定められている一定の状況または動的な状況に反応してトリガーされるものであり、シーケンスの実行を開始するものです。基本的な考え方は、次のようになります。ゲーム内で何かが起こり、それに対応するイベントが Kismet でトリガーされ、そのイベントに反応してアクションのシーケンスが実行される、ということになります。

Kismet でシーケンスをトリガーするために使用できるイベントは数種類あります。以下で解説しているイベントは、最もよく使用されるものです。

Level イベント

Level Loaded (レベルのロード) イベントは、シーケンスを含んでいるレベルのステータスに基づいて、シーケンスをトリガーするために便利なイベントです。以下は、それらのステータスです。

  • Loaded and Visible (ロードされビジブル) - レベルがメモリにロードされ、ビジブルになった時にトリガーされます。レベルがビジブルになった時にアクティベートしなければならないシーケンスをもつレベルをストリーミングする際に役立ちます。
  • Beginning of Level (レベルの開始) - レベルが初めてロードされた時にトリガーされます。レベルが初めてロードされた時に一度だけ起きるイベントのために役立ちます。
  • Level Reset - レベルがリセットされると必ずトリガーされます。レベルが起動または再起動するたびに発生するイベントのために役立ちます。

Player Interaction (プレイヤーインタラクション) イベント

レベル内に存在する Trigger または TriggerVolume と プレイヤーとのインタラクションに基づいて、特定のイベントが発生します。

Touch イベント

Touch (タッチ) イベントは、あるアクタが他のアクタを侵犯 (または「タッチ」) した時にトリガーされるイベントです。専門的には、Trigger または TriggerVolume がプレイヤーによってトリガーされることに限定されませんが、このタイプのイベントにとってそのような使われ方が極めて一般的です。このタイプのイベントは、プレイヤーの近くでアクティベートされるシーケンスを作成するのに役立ちます。

Used イベント

Used (使用) イベントは、特定のアクタ (通常は Trigger) から一定の範囲内で Use キー (デフォルトでは E) をプレイヤーが押すことによってトリガーされるイベントです。このタイプのイベントは、プレイヤーによって意図的に開始される必要があるシーケンス (例 : ボタンの押下やスイッチの切り替えなど) を作成するのに役立ちます。

Mover イベント

Mover (動くもの) イベントは、プレイヤーが乗った時にアクティベートされる昇降機や動く台をレベル内に作成するために使用されます。 これらのイベントには、「開く」、「閉じる」、「閉じ始める」前に既定の時間の間「開いた」ままにしておく機能が含まれています。

まず、 コンテンツブラウザ 内で、台 (platform) として使用したい StaticMesh (静的メッシュ) を選択します。次に、ビューポート内で右クリックし、メニューから [Add Actor] (アクタの追加) > [Add InterpActor...] (InterpActor… の追加) を選択します。

ex_mover_1.jpg

InterpActor のプロパティが表示されますので、 [Collision] (コリジョン) セクションを展開し、 [Collision Type] (コリジョンのタイプ) を COLLIDE_BlockAll (衝突_すべてをブロック) にセットします。

ex_mover_2.jpg

InterpActor が選択されたら、Kismet を開き、Kismet のワークスペースで右クリックし、 [New Event Using InterpActor... (InterpActor を使用する新たなイベント) > Mover] をコンテクストメニューから選択します。

ex_mover_3.jpg

これによって、特別な Mover イベントが配置されます。このイベントには、台を動かすために使用することができる Matinee が事前に接続されています。

ex_mover_4.jpg

ここから、 Matinee で動きをキーフレーム化すると、InterpActor がプレイヤーを動かし、サポートするようになります。プレイヤーがこの InterpActor にタッチすると、台が動き始めます。

これと同じような設定を実行する方法は多数あります。必ずしも、Kismet で右クリックして、InterpActor を Mover として追加する必要はありません。Matinee を自分で配置し、望ましい他の Kismet アクションによってトリガーすることも可能です。

条件

条件 (condition) とは、ある基準に基づいてシーケンスを 2 つ以上に分岐させることができる特別なシーケンスオブジェクトです。条件は、if / else 文や switch 文といった標準的なプログラミングに含まれている条件文と似ています。条件によって Kismet シーケンスは、基本的な意思決定を行うことができるようになるため、よりダイナミックで魅力的なものになります。

条件をシンプルに使った例としては、変数が特定の値である場合や、プレイヤーが特定の武器をもっている場合にのみシーケンスを実行するというものがあります。

ex_condition_weapon.jpg

より高度な条件の使用例としては、イベントをトリガーしたアクタが特定の型である場合にのみ実行されるシーケンスが複数ある、といったものが考えられます。

ex_condition_switch.jpg

ループ

ループも標準的なプログラミングから借りてこられたコンセプトです。ループは、特定の回数、あるいは、一定の条件が満たされるまで、あるいは、無限にアクションを繰り返すために使われます。ループを実行する方法は、そのタイプによって、1 つまたは複数あります。

単純な無限ループを実行する例としては、シーケンスの最後に置かれたあるアクションの出力から、そのシーケンスの始まりに置かれたアクションの入力に接続する方法があげられます。これによって、何回となくシーケンスが繰り返されることになります。

ex_loop_continuous.jpg

ALERT! 注意 : ループのイタレーション間に何らかの delay (遅延) を含まない継続的ループは、決して作成しないでください。遅延を実行するには、 Delay (遅延) アクション (入力または出力リンクの Activate Delay (遅延のアクティベート) を使用することができます。潜在的に実行されるアクションもあります。つまり、アクションが終了するまで実行されない出力をもつアクションがあります。このようなタイプの出力を使用するということは、ビルトインされた delay をもつことになり、したがって、追加 delay の代わりに使用することができるということになります。

既定の回数実行されるループ (すなわち、For ループ) を作成するには、 Counter (カウンタ) 条件 ( Int または Float ) を使用します。この条件は、1 つの変数の値をインクリメントまたはデクリメントさせ、それを他の変数と比較し、その比較結果に基づいて適切な出力をアクティベートします。Counter に接続されている シーケンスのうち 1 つ以上のシーケンスの出力を、カウンタの入力に接続することによって、ループを作成することができます。ただし、ループを終了させる条件を表す出力を、入力に再度接続しないように気をつけなければなりません。

ex_loop_for.jpg

特定の条件が満たされるまで実行されるループ (すなわち、While ループ) を作成するには、反復させるべきシーケンス (出力のうち 1 つだけがシーケンスのリピートを継続させることができるようなシーケンス) の最初または最後に条件を置きます。最初に条件を置くと、While ループができます。最後に置くと、Do-While ループができます。

(フルサイズの表示には画像をクリック)

Delay (遅延)

シーケンスまたはシーケンスの一部の実行を遅延させることは、Kismet シーケンスではごく一般的に行われることです。その理由は、レベルの開始時であろうが、あるいは、プレイヤーのスポーンであろうが、特定のアクションの実行であろうが、あるイベントを他のイベントと関連させて特定の時間に発生させる必要があるためです。

Delay を実行する方法は 2 つあり、そのどちらかを使います。最初の方法は、 Delay アクションを使用するものです。このアクションを使用すると、プロパティで (または変数を接続させることによって) 時間を指定することができるようになり、入力リンクがアクティベートされると、指定した時間の待機後に出力リンクがアクティベートされるようになります。当然のことながら、Delay を使用すると、他のアクションによって遅延の長さを決めることができることになります (そのためには、 Delay アクションに接続された変数の値を設定します)。また、遅延のための専用のアクションがあるため、シーケンスで遅延が生じていることが明白になります。

ex_delay.jpg

遅延を実行するもう 1 つの方法は、あらゆる入力および出力リンクにある Activate Delay (遅延のアクティベート) 機能を利用することです。リンクを右クリックし、[ Set Activate Delay ] (Activate Delay を設定) を選択すると、リンクがアクティベートされるまで遅延される時間 (単位 : 秒) を指定することができます。遅延の長さは、Kismet のワークスペース内でリンクの上方に表示されます。本質的には、 Delay アクションをシーケンスに追加するのと変わりませんが、アクションを追加する必要がなくなります。リンク自身が遅延を扱います。不変のハードコード化された値となるため、可変的な遅延を実現することは、当然のことながらできなくなります。どこで遅延が生じているのかやや不明瞭になりますが、スペースを節約し、シーケンスをコンパクトにすることができます。

ex_activate_delay.jpg

グローバル変数 (Global Variables)

Kismet ではグローバル変数に類似した変数を実装することが可能です。(ただし、「グローバル」という語の意味は、現在のパーシスタント レベルとストリーミング レベルのスコープに限定されます)。パーシスタント レベルで必要となる変数を作成し、全変数がもっている Var Name プロパティを利用して一意の名前を付けると、 Named Variables (名付けられた変数) を利用して、その変数とその値にアクセスすることができるようになります。グローバル変数の考え方は、非常に役立ちます。これによって、あるシーケンスに置かれた単一の変数に、他のシーケンスからアクセスできるようになりますが、利点はそれにとどまりません。Kismet をすっきりした形に留めておくこともできます。具体的には、すべての変数を一か所で集中管理し、さまざまなアクションに多数接続された単一の変数を使用するのではなく、複数の Named Variables を使用するのです。

変数は、最上位のシーケンス (すなわち、パーシスタント レベルの基本 Kismet シーケンス) に置くか、あるいは、少なくとも、他すべてのシーケンスの親 (そこに含まれている変数にアクセスすることができる) であるシーケンスに置かなければなりません。また、他のシーケンスがアクセスを試みた際にロードされていない可能性があるストリーミングレベルには、変数を置くべきではありません。

Switch (スイッチ)

Switch (スイッチ) を使用することによって、Switchがアクティベートされるたびに、異なるシーケンスを実行することができます。これは、使用される Switch のタイプによって、連続的にあるいはランダムに行うことができます。

Switch の使用例としては、プレイヤーが特定の数のアイテムを収集する必要がある、レベル内のミニゲームやクエストが考えられます。アイテムが拾われるたびに、同一の Switch がアクティベートされることにします。 Switch の出力は、各アクティベーションにともなって順番に実行されるものとします。これらの出力は、それぞれ、特定のアクションを実行するシーケンスにつなげることができます。(たとえば、変数の更新、メッセージの表示など。あるいは、最後の出力まで何もしないようにすることもできます)。最後の出力は、アイテムがすべて集められた時に起きるようなアクション (複数も) にすることも可能です。

Gate (ゲート)

他のイベントのシリーズが完了した時にのみ実行されるシーケンスの枝が必要となることがあります。どの時点であっても、何回であってもトリガーすることができるイベントで、かつ、他のイベントがトリガーされない限りプロパゲートされないイベント (例 : ロックされたドアは、最初にロックを解除されなければ開くことができません) を作ることができます。

このような関係にあるものをセットアップする方法として、 Gate を使用することができます。このアクションは、開閉することができ、開いている間に入力がアクティベートされた場合にのみ、出力がアクティベートされます。

ex_gate_switch.jpg

これに代わる方法としては、条件のステータスを保持するグローバルな Bool 変数を使用して、「開錠」イベントによってその変数の値がセットされるようにし、さらに、シーケンスをアクティベートする前に毎回その変数の値をチェックすることができます。

ex_gate_bool.jpg

これはとても望ましいものとは言えません。そもそも、 Gate アクションを作る原因となったものなのです。 Gate を使用すれば、同じ機能をすっきりとした形で実行することができます。

Object List (オブジェクトリスト)

Object List とは、その名のとおり、オブジェクトのリストのことです。これが役立つのは、多数のオブジェクト変数をアクションに接続させる際に、個々の変数ノードが大量に散乱するのを防ぎたい場合です。ただし、Object List は、極めてパワフルであるため、整理整頓にとどまらずに多数の利用法があります。Object List は、標準的なプログラミングに備わっている配列やその他のリストなどと同じように使用することができます。たとえば、ワールドにスポーンされた各プレイヤーへの参照を Object List に追加し、さらに、そのリストをイタレートして各プレイヤーに何らかのアクションを実行することができます。また、あるボリュームに入ったオブジェクトすべてのリストを保持し、他のイベントに反応して、それらのオブジェクト全部にダメージを与えることができます。

Object List を使用する際に利用できる主なアクションは、Access ObjectList、IsIn ObjectList、Modify ObjectList の 3 つです。

IsIn ObjectList と Modify ObjectList は、通常、オブジェクトを Object List に追加する場合と Object List から削除する場合に使用します。

ex_objlist_setup.jpg

Access ObjectList は、リストをイテレートして現在のアイテムへの参照を得るために使用するアクションです。

ex_objlist_access.jpg

Timer (タイマー)

Timer アクションは、たいてい、マップのテストやデバッギングのために使用されます。「Gears of War」のシングルプレイヤー用シナリオでは、敵の集団が現れるため、各バトルに要する時間が問題になります。バトルに必要な時間が大体分かれば、バトルに関連した他のイベントを開始すべき時も、把握しやすくなります。たとえば、あるバトルに 30 秒かかるのであれば、15 秒が経過した時点で、壁がプレイヤーに向かって迫り始めるようにすることによって、プレイヤーにプレッシャーを与えることができます。Timer には、これといって特定の使用方法はありませんが、シネマティックスの時間を計測するのに便利なツールです。

具体例


このセクションでは、シーケンスの具体的な例をあげて、上記で詳述したコンセプトの多くと、その他の一般的な Kismet の使用法について説明しています。

近接ドア

このシーケンス例では、プレイヤーが一定の範囲に入ると自動的に開くドアの作成について説明します。

ex_door_proximity.jpg

シーケンスをトリガーするのは、ドアのところに位置する Trigger と関連づけられた Touch イベントです。Trigger の半径 (範囲) によって、ドアを開くのにプレイヤーがどの程度接近しなければならないのかを調整することができます。Touch イベントの Max Trigger Count (最大トリガー数) が、0 にセットされているため、イベントを無限にトリガーすることができます。

Touch イベントの Touched 出力によって、Matinee の Play (再生) 入力がアクティベートされ、ドア (複数も) の開動作がアニメートされます。 UnTouched 出力によって、Matinee の Reverse 入力がアクティベートされ、ドア (複数も) が閉じられます。

手動ドア

このシーケンス例では、プレイヤーが Use キーを押して手動で開かなければならないドアの作成について説明します。

ex_door_manual.jpg

シーケンスをトリガーするのは、ドアのところに位置する Trigger と関連づけられた Used イベントです。Touch イベントの Max Trigger Count (最大トリガー数) が、0 にセットされているため、イベントを無限にトリガーすることができます。 Interact Distance (インタラクト距離) は、プレイヤーが Trigger からどの程度まで離れてドアを開くことができるか調整するために使用します。

Touch イベントの Used 出力によって、Matinee の Play (再生) 入力がアクティベートされ、ドア (複数も) の開動作がアニメートされます。Matinee の Completed 出力から Reverse 入力に接続されます。この時、3.0 秒の Activate Delay (遅延のアクティベート) をともなうことによって、ドア (複数も) が閉じられます。この値によって、ドアを開いたままにしておく時間を調整することができます。

この設定を別の方法で行うのであれば、Used イベントの Used 出力と Matinee の間で、2 個の出力リンクをもった Switch アクションを使用することが考えられます。1 番目の出力は、ドアを開く Play 入力に接続し、2 番目の出力は、ドアを閉じる Reverse 入力に接続します。こうすることによって、ループと Activate Delay を使用することなくドアの開閉をプレイヤーが行うことができるようになります。

ex_door_manual_alt.jpg

ダメージカメラの振動

このシーケンス例では、プレイヤーのカメラに、既定のカメラアニメーション (例 : ダメージカメラの振動) を再生させる方法について説明します。

(フルサイズの表示には画像をクリック)

プレイヤーは、スポーンされると、Attach To Event (イベントへのアタッチ) アクションを経由して、Take Damage (ダメージを受ける) にアタッチされます。Take Damage イベントは、プレイヤーがダメージを受けるたびにトリガーするように設定されています。( Damage Threshold (ダメージ閾値) = 1.0)。また、無限回トリガーするように設定されています ( Max Trigger Amount (最大トリガー回数= 0)。ダメージカウンターは、トグル (toggle 切り替え) された時にリセットされるように設定されています。( Reset Damage On Toggle (トグル時にダメージをリセット) = True)。 Reset Damage On Toggle (トグル時にダメージをリセット) が重要である理由は、 Damage Taken (被ダメージ) 変数の出力が、常に今回受けたダメージを出力するようにしなければならないにもかかわらず、トリガーされる度にイベントをトグルしてダメージカウンターをリセットしなければ、イベントのダメージカウンターの累積を出力してしまうためです。

Float 変数が Damage Taken 変数の出力と接続されて、受けたダメージ量を保持します。

Take Damage イベントは、トリガーされると、Take Damage をトグルするようにセットされている 2 つの Toggle アクションをアクティベートし、ダメージカウンターをリセットします。

また、計算のシリーズが Take Damage イベントによってアクティベートされます。これらの計算シリーズは、CameraAnim を再生する時に使われる再生レート (play rate) と強度値 (intensity value) を取得するために使用されるものです。ダメージ量は、10.0 で除算されます。この計算結果は CameraAnim のための intensity Scale (強度スケール) になります。さらに、この値がインバート (反転) されて、その結果が CameraAnim の再生 Rate (レート) として使用されます。

Play Camera Animation (カメラアニメーションの再生) アクションは、ダメージ振動 CameraAnim を再生するために使用されます。 CameraAnim の Intensity Scale (強度スケール) と Rate (レート) を調整するには、関連する変数をエクスポーズします。それには、Play Camera Animation アクションを右クリックし、 [Expose Variable] (変数のエクスポーズ) > [Intensity Scale] (強度スケール) および [Expose Variable] (変数のエクスポーズ) > [Rate] を選択します。2 つの Float 変数は、これらの新たにエクスポーズされた変数入力に接続され、Player Spawned イベントの Instigator (インスティゲータ) Object変数が、 Target 変数の入力に接続されます。

注意 : このシーケンスが機能するのは、プレイヤーがカスタムの Camera クラスを使用し、カメラビューポイントを計算する CalcCamera() メソッドを用いない場合に限ります。

ホーミングビーコン

このシーケンス例では、ホーミングビーコンのサウンドを作成する方法について説明します。ホーミングビーコンのサウンドは、プレイヤーからターゲットまでの距離に基づいてそのピッチ (音の高さ) と音量が調節されます。

(フルサイズの表示には画像をクリック)

Level Loaded (レベルのロード) イベントによってレベルが起動すると、このシーケンスが開始されます。シーケンスが開始されると、Get Distance (距離の取得) アクションがアクティベートされます。このアクションは、プレイヤーとホーミングターゲットの距離を取得し、それを Float 変数に格納します。さらに、この値は HomingRadius (ホーミング半径) で除算されます。これによって、距離の値は正規化されます。つぎに、この値はバイアスをかけられ、さらにインバートされて、音量とピッチとして使用される最終的な値である ModMultiplier (調整乗数) となります。

Play Sound (サウンドの再生) は、サウンドを再生するために使用されます。Play の入力は、調整計算の最後の Divide アクションによってアクティベートされます。 Volume Multiplier (音量乗数) 変数の入力、および、 Pitch Multiplier (ピッチ上数) 変数の入力がエクスポーズされ、 ModMultiplier が両者に接続されます。Finished 出力が、Get Distance (距離の取得) の入力に戻って接続され、再度プロセスが開始されます。

歩哨 AI をリスポーンする

このシーケンス例では、AI エンティティをスポーンおよび制御する方法について説明します。

(フルサイズの表示には画像をクリック)

シーケンスは、Level Loaded (レベルのロード) イベントの Beginning of Level (レベルの開始) 出力によってトリガーされます。これによって、指定された PathNode (パスノード) に単一の AI エンティティをスポーンさせる UTActorFactoryAI Factory (ファクトリー) をともなう Actor Factory (アクタファクトリー) がアクティベートされます。 スポーンされた AI への参照は、空の Object 変数に保存されます。(この例では、 SpawnedBot という名前にします)。

2 つに分かれたループが、Actor Factory の Finished (完了) 出力によってアクティベートされます。最初のループは、AI エンティティの発砲状態を制御します。まず、 SpawnedBot (ボットのスポーン) 変数が空の Object 変数と比較されます。そのためには、A = B 出力に 0.25 という Activate Delay (遅延のアクティベート) がともなった Compare Object (オブジェクトの比較) 条件が使用されます。比較に失敗すると、 SpawnedBot からプレイヤーまで Trace (トレース) が実行されます。遮蔽物が見つからなかった場合は、Start Firing At (標的に発砲) アクションを通じて、 SpawnedBot がプレイヤーに向かって発砲します。Start Firing At の出力は、Compare Object 条件に戻って接続され、ループが再び始まります。Trace によって遮蔽物が見つかった場合は、 Spawned Bot が発砲を中止し、Stop Firing (発砲中止) アクションの出力が、Compare Object 条件の入力に戻って接続され、ループが再び始まります。

第 2 のループは、AI エンティティの動きを制御します。ここでもやはり、Compare Object 条件を使って、 SpawnedBot 変数と空の Object 変数を比較します。比較に失敗すると、Move To Actor (アクタに移動) アクションによって、 SpawnedBot が異なる Pathnode (パスノード) に進むように誘導されます。 Finished 出力によって、別の Move To Actor アクションがアクティベートされ、 SpawnedBot が元の Pathnode に戻るように誘導されます。2 つ目の Move To Actor アクションの Finished 出力は、Compare Object 条件の入力に戻って接続され、ループが再び始まります。この継続ループには遅延は必要ありません。というのは、 Finished 出力を使用することによって、AI エンティティがある位置から他の位置に移動し、自然に遅延が備わるためです。

Actor Factory アクションの Finished 出力 は、Attach To Event アクションもアクティベートさせます。この Attach To Event アクションは、 SpawnedBot を Death (死) イベントに関連づけます。Death イベントは、Set Object (オブジェクトのセット) アクションをアクティベートさせ、 SpawnedBot への参照を削除するとともに、2 つのループが循環するのを中止させます。Set Object の出力は、Actor Factory の Spawn Actor 入力に戻って接続されます。その際、3.0 秒の Activate Delay をともなうため、新たな AI エンティティがリスポーンされるまでに少し遅延が生じます。

Kismet による武器

以下の 1 組みのシーケンス例では、速射武器を Kismet だけで作成する方法について説明します。説明されている事項は、Trace (トレース)、Actor Attachment (アクタのアタッチメント)、Console Command (コンソールコマンド)、Console Event (コンソールイベント)、Particle Event (パーティクルイベント)、アクタにダメージを与える方法です。

ex_weapon.jpg

最初のシーケンスは、Emitter (エミッタ) を WeaponPoint (武器地点) ソケットにアタッチすることによってプレイヤーをセットアップします。(あらゆる移動可能なアクタを Emitter にすることができます。Emitter が使用される理由は、すでにレベル内に存在していたからであり、発砲シーケンスで使用される際の位置が問題にならないからです)。 (また、ソケットは、Y 軸に平行な 3000.0 の Relative Offset (相対オフセット) をともないます。この値は、武器の有効範囲を表します)。さらに、 BEHINDVIEW (背後からの視点) コンソールコマンドが実行されることによって、ゲームが三人称視点に置かれます。これが必要であるのは、アタッチメントがカメラのために適切に回転できるようにするためです。

MainFire (主要な発砲) イベント名に関連づけられた Console Event が使用されて、発砲が処理されます。UDKInput.ini が編集されて、 CauseEvent MainFire (主要な発砲イベントを起こす) が、武器を発砲するための現在のバインディングに追加されました。

Bindings=(Name="GBA_Fire",Command="CauseEvent MainFire | StartFire | OnRelease StopFire")

これによって、プレイヤーからアタッチされた Emitter までのトレースを実行する Trace アクションがアクティベートされます。トレースをさえぎるものがある場合 (つまり途中で何かをヒットした場合) は、 Instigator (インスティゲータ) としてプレイヤーを使用する Modify Health (ヘルス値の修正) アクションによって、 HitObject (ヒットされたオブジェクト) がダメージを受けます。同時に、Particle Event Generator (パーティクルイベントジェネレーター) が使用されることによって、Emitter が遮蔽物の位置にパーティクルを噴出させ、血飛沫などのヒットエフェクトをシミュレートします。使用される ParticleSystem には、 HitEffect ( Event Names 変数の入力に渡される名前と同じ) を待ち受けるスポーンイベント受け取りモジュールがあります。これは、10 個のパーティクルをスポーンします。

このエフェクトを拡張するには、Trace アクション上にある Distance 変数の出力を使用することができます。これを使用すると、ヒットされたアクタからプレイヤーまでの距離に基づき、動的なダメージ量を計算することができます。別の方法としては、武器メッシュをプレイヤーのメッシュにアタッチさせることです。あるいは、現在の武器メッシュをデタッチするピックアップシステムを作成し、新たな武器メッシュをプレイヤーにアタッチさせ、完全な武器インベントリ システムを作成するために使用される Emitter アクタを変更することです。このような機能は通常グローバルなものであるため、普通はスクリプトを通じて行われます。しかし、シューティングのミニゲームやそれに類似するものを含むレベルがゲームに 1 つ存在する場合のことを考えてみましょう。そのような場合は、創造的な Kismet のスクリプト処理がうってつけです。

敵の襲来

このシーケンス例では、敵の襲来 (wave) を新たにスポーンするシステムをセットアップする方法について説明します。このシステムは、これまでにスポーンした襲来の敵がすべて滅ぼされるたびに、新たな襲来をスポーンします。この例では、ループ、オブジェクトリスト、条件が利用されています。

(フルサイズの表示には画像をクリック)

シーケンスは、まず Level Loaded イベントの Beginning of Level 出力によってアクティベートされます。(ただし、どのようなイベントによってもトリガーされることが可能です)。これによって、一組の扉が開く Matinee が再生されます。この扉の背後で敵がスポーンします。

扉が開かれると、Matinee が完了し、UTActorFactoryAI Factory をともなった Actor Factor が、AI エンティティをスポーンします。 Spawned (スポーンされた) AI は、Attach To Event アクションによって Death イベントにアタッチされます。また、 Spawned (スポーンされた) AI は、Object List に追加され、リスト内のアイテム数がチェックされます。敵の数が最大数に満たない場合は、シーケンスがループして Actor Factor に戻ります。そうでない場合は、 Reverse (反転) で Matinee を再生して、扉を閉め、スポーンのループを終了します。

Death イベントの出力によって、すべての敵を保持している Object List から死んだ Pawn が削除されます。さらに、リストの中にある敵の数が、再度チェックされます。敵がもう残っていない場合 (リストのカウントが 0 の場合)、Matinee が再度再生されて、次の襲来が開始されます。

以上は、もちろんのこと基本的な枠組みに過ぎません。これを拡張することによって、襲来する数を追跡管理し、各襲来の開始時、終了時にメッセージを表示することは簡単にできます。また、各襲来でスポーンされる敵の数を増やすことによって ( MaxEnemies 変数を利用して)、徐々に難しくすることもできます。