紹介記事
完全図解,無償配布のUnrealEngine 3開発キットで3Dゲームを作ってみよう
Botを出現させる
これまでの部分は,ゲームの舞台となるレベルをどう作っていくかということしか扱っていませんでした。レベルだけ作ってもゲームにはなりません。歩いたり撃ったりは標準装備ですので,あとは敵が出てくれば最低限FPSの体裁にはなります。
UnrealEngineではさまざまなAIキャラクター(Bot)をゲーム内に登場させることができ,基本的な設定を行われたBotが最初から用意されています。
ゲーム内でこのBotを使用してみましょう。詳しくは,公式サイトにあるチュートリアルビデオのTopDownゲームの19本目以降を見てほしいのですが,やや複雑になりますので,ここでは要点だけを解説します。最低限の処理として単体の敵を出して攻撃させるまでの処理を組んでみましょう。
まず,Unreal Editorで簡単なレベルを作ってビルドしておいてください。床と光源さえあれば大丈夫です。
次に,コンテンツブラウザを開き,上のタブで「Actorクラス」となっている部分をクリックしてください。表示がActor一覧に切り替わります。ここで「Note」という部分を軽くクリックして選択します。
Unreal Editorに戻って,レベル上の適当な位置で右クリックし,[ここにNoteを追加]ないしは[最近使用した項目を追加]−[Noteを追加]を選択します。画面上には緑のメモ帳のようなものが置かれるのが分かると思います。Noteというのは,このように位置を記録して,ほかの処理に渡す際などに使われるもののようです。
この際に,一つだけ注意点があります。Noteは床やほかのオブジェクトにめり込んだ状態にしないでください(単に置くとめり込む)。実行時に警告が発生して,Botの生成ができません。
そのまま(Noteが選択された状態で),一番上のツールバーにある「K」に矢印がついたアイコンを押してKismetを開きます。Kismetとは,Unreal Engineでちょっとした処理を記述するのに使われるビジュアルプログラミング言語環境です。「Kismet」自体は,イスラム系の国での「運命」を意味する単語に由来しています。
Kismetウィンドウ上で右クリックすると「新しいオブジェクト変数(Note_0を使用)」といったメニュー項目が見えますので,それを選択します。これでKismet上でNote_0の位置情報を利用できるようになります。
次に,これから作る処理の起動条件を指定します。
右クリックで[新しいイベント]−「Level Loaded」を選んでください。
さらに別の場所で右クリックし,[新しいアクション]−[Actor]のアクションから[ActorFactory]を使用します。ActorFactoryは,ゲームの実行中,動的にいろんなアクタを追加できる機能です。
画面に出てきた図形は,Ctrlキーを押しながら操作すると自由な位置に配置できますので,画面を参考に配置してください。
これから,作成したレベルがPCにロードされ,ゲームが開始されたら新しいアクタとして敵キャラをNote_0の位置に生成する処理をKismetで組んでいきます。
Level Loadedの「Beginning Level」の突起を引っ張って,Actor FactoryのSpawn Actorの部分に結合します。
さらにActorFactoryの「Spawn Point」の突起から,先ほどのNote_0に線を接続します。
次に,一番肝心な部分のActorFactoryの設定を行います。ActorFactoryを選択したときに下に出るプロパティ部分で,Factoryのところを見ます。「None」となにも指定されていませんので,生成したいアクタを指定します。右端の青い三角を押すと指定できるものの一覧が出ますので,その中から「UTActorFactoryAI」を選択します。
さらにFactoryの左にある黒い横三角マークをクリックすると,その詳細が設定できますので,Pawn ClassにUTPawnを選択し,その上のGive Default Inventoryにチェックを入れ,Inventory Listの右の緑の+マークをクリックし,さらにそれを開いてLinkGunあたりを初期装備として持たせる指定にします。
お待たせしました。この状態で適当に「ここから再生」を行えば,画面上に武器を持ったBotが表示されることが分かります。エラーが出る場合は,Noteが地面にめり込んでいないかを確認してください。
Kismetには,以下の要素が含まれています。
- イベント:どういう条件で処理が始まるか
- アクション:実際の処理
- 条件:処理の振り分けなど
- マチネー:Unrealのアニメーション管理システム(後述)
- 変数:処理中に使われる値を保持し受け渡す
- オブジェクト:アクタや処理中の複雑な変数など
処理は必ずイベントから始まり,アクションはオブジェクトに結びついているので,どのオブジェクトの動作かを「Target」で指定します。処理の流れとデータの流れは色の違う線で結んでいきます。演算や比較では,AとBの2種類の変数が必要です。
どのような条件で呼び出すことができ,どのような動作をさせられるのかが分かれば,FPS以外にも簡単なゲームを組むことはできそうです。
Botに攻撃させてみる
Botも単に出現させただけでは動きませんので,面白くありません。プレイヤーを攻撃するようにしてみましょう。
先ほどの図の隣に,右メニューから[新しいアクション]−[AI]−[Start Firing At]を選択します。
ActorFactoryの「Finished」からStart Firing Atの「In」を線で結びます。
ActorFactoryの「Spawned」の三角コネクタにカーソルを合わせて右クリックし,新しいObject変数を生成してください。この変数が,生成されたBotを意味するものとなります。Start Firing Atの処理を行う主体として登録するには,Botの変数と「Target」の部分を結びます。
どこを狙って撃つかを指定するため,右クリックメニューから,[新規の変数]−[Player]−[Player]を生成し,これを「Fire At」と結びます。
以上で「Factoryで作られたBotが,プレイヤーを狙って攻撃開始」という一連の処理が指定されました。この状態で,再生するとBotがプレイヤーめがけて攻撃するようになります。
Botを制御してみる
Botのエイミングは完璧で,どんどん連射をしてきます。避けながら動いていればあまり当たることはないのですが,撃ち返そうと立ち止まるとドカッと喰らいます。いまは動かないからよいのですが,なんとなく嫌な感じです。
ちょっと手加減してもらいましょう。
Start Firing Atの処理に続けて,右メニューから[新しいアクション]−[AI]−[Stop Firing]を入れます。主体となるのは生成されたBotですので,Targetは攻撃と同じものをつないでおきます。
Start Firing Atの「Out」から線を伸ばして,Stop Firingの「In」につなぎます。Stop Firingの「Out」は,Start Firing Atの「In」に戻します。
ここで二つの「Out」コネクタのところで右クリックして,[アクティブ化の遅延を設定]しておきましょう。とりあえず,Start Firing AtのOutに0.5秒,Stop Firing側に1.5秒を入れておきます。ディレイというより,その処理を指定時間分持続するといった雰囲気です。
0.5秒撃って1.5秒休みますので,これでかなり手加減してくれるようになります。
さて,1.5秒休んで0.5秒撃ってというループは,Botが死んだあとでも回るらしく,Botを倒したあとでは画面にずっと警告が表示され続けます。処理の途中にBotが死んだかどうかの判定を入れておきましょう。
Botの状態を示す変数を用意し,Botを作ると1を足して,死ぬと1を引きます。ここが1でないと,射撃ループが進まないように判定を入れます。基本構想は以上です。
チュートリアルビデオを見るとBotの数はActorFactoryのSpawn Countでインクリメントされるみたいでしたので,そこにIntの変数を作り,Pawnが死んだら-1を行い,結果を変数に書き戻すことにします。試してみるとなんとなくSpawn Countがインクリメントされてないみたいでしたので,最初から1を入れておきます(そうなると,ActorFactoryにつなぐ意味もないのですけど)。
Botが破壊されると,変数から1を引きます。
足し算/引き算は,[新しいアクション]−[Math]−[Add Int]でなんとかなりそうです。条件判定も[新しい条件]−[Comparison]−[Compare Int]でいけそうです。
問題は,Botが死んだのを判定する部分です。
[新しいイベント]−[Pawn]−[Death]というのがそれっぽいので,とりあえず,組んでいきます。
単に指定してもDeathのイベントが起動されている様子はありません。Targetの指定もありませんので,手の施しようがありません。
基本的にKismetでは,レベル作成時にあるオブジェクトについては,そのオブジェクトを選択したうえでメニューを開くことで,そのオブジェクトを起点としたイベントを指定できます。今回のように,ゲーム開始後に動的に作られたオブジェクトに関しては,動的バインドという操作をする必要があります。
生成されたBotにイベントを付加するには,[新しいアクション]−[Event]−[Attach To Event]というのを追加し,どこかから処理の流れを拾ってきます。ここでは,Actor Factoryの「Out」につなぎました。
続いて,「Attachee」の部分をBotオブジェクトに接続します。さらに,「Event」から線を伸ばし,Deathの頭の部分に接続します。コネクタ同士をつないでいた,これまでとは違ったルールのつなぎ方になります。
ざっと見て分かるように,処理の流れは黒い線,オブジェクトの指定/割り当てはマゼンタの線,整数値はシアンの線になっています。赤い線はイベントですね。なんとなくやっても意外と簡単に組めるのですが,仕上がり的に見た目に非常に汚いものになってしまいました。まさにスパゲッティという感じ? 一つの図にまとめずに,複数に分けて描くのがよさそうです……。
全体的に,仕様の見当がつきづらく,デバッグも大変です。わざわざビジュアルプログラミング環境にする意味はあったのでしょうか。
とにかく,このようにKismetで試行錯誤していけば,Botをある程度思いどおりに制御することは可能です。しかし,それでは面倒だという人には,とっておきのオプションが用意されています。
それはActorFactoryでPawnを生成するときに[Force Deathmatch AI?]にチェックを入れておくことです。これで勝手に動き回って撃ちまくってくれます。UnrealEngineでは,もっと細かくAIを制御して行動する範囲や移動ルートなどを設定できますが,Kismetに慣れるまでは便利なオプションです。
複数のBotを出現させる
もっと実用的な実装法,つまり複数のBotを出して思いどおりに制御したいときは,オブジェクトリストを使った操作になってちょっと複雑になりますので,まずはチュートリアルビデオのとおりにKismetを操作することをお勧めします。
Noteなどの処理に使うオブジェクトを順番にObjectList型の変数に入れ,順番に呼び出してやれば1か所でオブジェクト関係の処理をさせることができます。
極限まで簡略化して独自にやろうとしてみたのですが,どうもうまくいきません……。初期化を端折って,初期値の指定をオブジェクトのプロパティで直接ObjectListに入れてみたのですが,変数の型だけ入って,重要な情報は失われている感じです。
さらにチュートリアルを見ても,ループを組んでインデックスで処理したりはしていませんので,あまり効率よくなってない気はします。一つずつ代入処理を並べるくらいだったら……確実に動くものを多数コピーして使うというのもアリだという気はしています。変更を加えるときに多少注意が必要ですが,おそらく速度的にも有利かと思われます。
ということで,丸ごとコピペして,Noteだけ置き換えてください。
Botを移動させる
出現,攻撃に続いて,Botの移動をやってみましょう。
Kismetを開き,Botが出現するところまで作っておいてください。次に移動先としてNoteをもう一つ置きます。最初のNoteをAltキーを押した状態でつかんで移動させるとコピーができます。
右クリックの[新しいアクション]−[AI]−[Move To Actor]を選択します。
Actor Factoryからの「Finished」とMove To Actorの「In」を接続します。次にTargetにはActor Factoryの「Spawned」から生成したオブジェクトをつなぎます。「Destination」には,新しい位置のNoteをオブジェクト変数として与えてください。
これで実行すれば,初期位置から指定したところまでBotが走ります。
行き先を入れ換えれば簡単に往復動作なども組み立て可能です。
右手側に銃を抱えている関係で,向きによっては背中向きになったりするので,視線はPlayer方向にしておきましょう。右クリックで[新規の変数]−[Player]−[Player]を作り,「Look At」から線を伸ばしてください。
これで完成です。
先ほど作った攻撃するタイプに移動処理を加えてみたのが,以下のものです。2体のBotが互いに位置を入れ換えながら移動し,移動先で攻撃してくる処理になります。ごく簡単に説明しておきましょう。
移動と攻撃,攻撃停止の処理を2か所ずつで行っていますが,死亡判定は1か所なので,これも二つにしたほうがよいかもしれません。
ちなみに,いろんなものに付いている「Instigator」というのが気になっている人もいるかと思います。これは,なにかのオブジェクトがアクションやイベントを起こした際に,その原因となったオブジェクトを得るもののようです。例えば,Botがダメージを受けた場合,ダメージを受けた処理を行うのは,そのBotオブジェクトですが,ダメージを与えたものがInstigatorから得られるようです。詳しく試していないので使いどころはよく分かりませんが。
Kismetでの処理記述は,UDKのゴールではありません。汎用のプログラミングのためにはUnreal Scriptが用意されており,さらに詳細な記述が可能になっています。Kismetでどうしてもできない処理が出てきたら,そちらに進んでください。
Third Person Viewにする
これまでの実行例はすべてFPS風のものになっていました。UDKでは,デフォルトでFPSの動作一式が組み込まれていますので,なにもしないとFirst Person View(一人称視点)のままです。自分の身体も見たいという人のために,Third Person View(三人称視点)に切り換えてみましょう。
前述のように公式サイトにTop Downタイプのゲームを作るムービーが公開されており,このあたりの処理は,その3番目のものに詳しいのですが,ここで要点だけを軽くまとめておきます。
Unreal Editorのプルダウンメニューから[表示]−[ワールドプロパティ]を選択します(こんなところにこんなものがあったんですねえ)。ここの,「My Map Info」の部分で「No Default Inventory For Play」にチェックを入れてください。これで初期装備を持たないキャラクターが登場します。武器管理などの処理が手動となりますが,同時に画面上に腕やキャレットが出なくなります。
三人称視点ですから,プレイヤー以外の視点が必要になります。そこでカメラを追加して,そこからプレイヤーを見るようにします。さらにカメラがプレイヤーについて移動するような処理を作れば,三人称視点が実現できます。
では新しいカメラを設置しましょう。コンテンツブラウザを開いて,Actorクラス一覧に切り換えます。Noteの配置と同様な手順で上から2番目のCameraActorを選択して,レベル内に配置してください。
Kismetを開き,起動条件を入れておきましょう。ここでは右クリックメニューから[新しいイベント]−[Level Startup]を使いました。
続いて,[新しいアクション]−[Actor]−[Attach to Actor]を追加します。
ここではカメラがプレイヤーについて移動するような処理を記述しますので,主体となるカメラとプレイヤーのオブジェクトを明示します。エディタでカメラを選択して,右クリックメニューからカメラオブジェクトを,右クリックメニューの[新規の変数]−[Player]−[Player]からプレイヤーのオブジェクトを作ってください。
この二つのオブジェクトをAttach to Actorに接続します。TargetからPlayerに,AttachmentからCameraActorに線をつないでください。
念のため,Playerのプロパティのところで「All Players?」のチェックを外しておきます。現状ではマルチプレイヤーでないので,あまり関係はないのですが,これでPlayer0だけを指定することができます。
次に,カメラの向きをずっとプレイヤーを追うように調整します。[新しいアクション]−[Camera]−[Set Camera Target]を選択します。
Set Camera Targetはカメラに対して出す指示ではないかという気もするのですが,被写体側のアクションになっています。図のように線をつないでください。
次に,カメラをプレイヤーに対してどの位置に置くかを指定します。「Attach to Actor」を選択して,左下のプロパティから「Relative Offset」をクリックして開き,ここでは,
X: -500
Y: 0
Z: 200
を設定してみました。この状態で再生すると,以下のような感じになります。
数値は好みに合わせて調整してください。
- 関連タイトル:
Unreal Engine
- この記事のURL: