UDN
Search public documentation:

UnrealScriptGameFlowJP
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 ゲームのフロー
UE3 ホーム > ゲームプレイ プログラミング > UnrealScript ゲームのフロー

UnrealScript ゲームのフロー

概要


「Unreal Engine 3」によるゲームのフローは、他の開発技術を利用してきたプログラマーにとって、あまり馴染みのないものかもしれません。あるいは、「Unreal Engine 3」の機能に単に不慣れな場合もあるでしょう。本ドキュメントの目標は、ゲーム内のフローを概説するとともに、フローに役立つ重要な機能を取り上げることです。これは、必要に応じてゲームをカスタマイズする場合に役立ちます。

イベントの一般的なフローは以下のとおりです。

+ エンジンが初期化されます。
|--+ エンジンがマップをロードします。
   |--- ゲームタイプがセットされます。
   |--+ ゲームプレイが初期化されます。
   |  |--- GameInfo:InitGame() が呼び出されて、ゲームタイプを初期化します。
   |  |--- Actor::PreBeginPlay() が呼び出されて、すべてのアクタを初期化します。
   |  |--- Actor::PostBeginPlay() が呼び出されて、すべてのアクタを初期化します。
   |--+ プレイヤーが加わります。
      |--- GameInfo::Login() がゲームタイプ上で呼び出されて、このプレイヤーのスポーンを処理します。
      |--- GameInfo::PostLogin() がゲームタイプ上で呼び出されて、この新たなプレイヤーを処理します。

gameflow.jpg

ムービーのセットアップ


エンジンが起動すると、一連の起動ムービーが再生されます。このムービーには通常、Powered by Unreal のムービーや Epic Games のムービーなどが含まれますが、他にもムービーを追加することは可能です。この起動ムービーは、フルスクリーンの映像 (.bik) です。 DefaultEngine.ini ファイルの FullScreenMovie] セクションの中で指定される StartupMovies 配列によって指定されます。

[FullScreenMovie]
+StartupMovies=UDKFrontEnd.udk_loading

マップのロード


「Unreal Engine 3」において、あらゆるゲームプレイとインタラクションはマップ内で行われます。エンジンは、起動すると常にマップをロードします。マップをロードする過程で一連のイベントが開始されます。このイベントによって、新たなマップが開かれるだけではなく、新たなゲームタイプも初期化され、さらにマッチ (競技) も開始されます。

エントリーマップ

ゲームが起動したときにロードするマップは、コマンドラインで指定することができます。マップが指定されなかった場合は、デフォルトのマップがロードされます。通常は、マップを指定しません。したがって、デフォルトのマップ (エントリーマップ) がロードされることになります。

デフォルトのマップは、 DefaultEngine.ini ファイルの [URL] セクションで指定します。

[URL]
Map=UDKFrontEndMap.udk

通常、デフォルトのマップは、プレイヤーのスタート地点をともなった、とてもシンプルなマップです。このマップは、ゲームプレイをホストするためのものではなく、ゲームのメインメニューをロードするためのものです。 UDKFrontEndMap.udk マップの全体像は次のようになります。

entrymap.jpg

メインメニュー

ゲームにおいて特定のメニューをメインメニューとして使用できるようにする特別な機能はありません。また、ゲームを起動するとメインメニューに入る機能もありません。上記で簡単に触れたように、メインメニューをロードするのは、ゲーム起動時にロードされるマップの役目です。

これによって、ゲームの起動方法を非常に柔軟に制御できるようになります。たとえば、ゲームが起動すると即座にメインメニューを表示することが可能です。また、ゲーム起動時に、メインメニューに遷移していくシネマティックスを表示することも可能です。さらに、メインメニューを表示する前に、ゲームプレイを少しばかり行うことも可能です。実際のところ、必要な場合は、メインメニューという概念をすべて省略してしまうことすら可能なのです。

メニューは Kismet を使用して開きます。以下は、 UDKFrontEndMap.udk マップからメインメニューをロードする Kismet の例です。

mainmenu_kismet.jpg

ロード画面

あるマップから別のマップに遷移する場合は、ロード画面が表示されます。ロード画面は、実際のところ、 DefaultEngine.ini ファイルの FullScreenMovie] セクションで指定された LoadMapMovies 配列からランダムに選択されたフルスクリーン映像 (.bik) です。

[FullScreenMovie]
+LoadMapMovies=UDKFrontEnd.udk_loading

ゲームの起動


「Unreal」では、「ゲーム」という用語がいろいろな意味で使われます。今回は、ゲームプレイと新たなマップがロードされた後に起きるイベントのことを意味します。

ゲームの Init

他のあらゆるスクリプト (あらゆるアクタの PreBeginplay() イベントも含めて) が実行される前に、当該 GameInfoInitGame() イベントが呼び出されます。このイベントの主な目的は、ゲームタイプが、自身のパラメータをセットアップできるようにするとともに、必要なヘルパークラスをスポーンできるようにすることです。

event InitGame( string Options, out string ErrorMessage )

PreBeginPlay

PreBeginPlay() は、アクタのスクリプトが実行された後で、アクタ上で最初に呼び出されるスクリプト関数です。この関数名からは、ゲームプレイが開始される前に呼び出されることが分かります。(これに当てはまるのは、ゲーム起動時にアクタが存在する場合です)。アクタがプレイ中にスポーンされる場合は、ゲームプレイが開始された後であっても、このイベントが呼び出されます。非常に特殊な初期化をここで行うことができますが、覚えておかなければならないことがあります。それは、この時点でアクタのコンポーネントがまだ初期化されておらず、外部のオブジェクトを確実に初期化できる手段もないということです。

event PreBeginPlay()

PostBeginPlay

PostBeginPlay() イベントが呼び出される時期は、 PreBeginPlay() イベントによってすべての他のアクタが初期化された後です。通常、このイベントの目的は、プロパティを初期化し、ワールド内の他のアクタへの参照を見つけ、他の一般的な初期化を実行することです。このイベントは、スクリプトにおいてアクタのコンストラクタに相当するものと考えることができます。ただし、初期化するために、アクタで特殊なイベントを使用しなければならないものも、他にまだあります。たとえば、アニメーションと AnimTree に関係する初期化は、 PostInitAnimTree() イベントで実行するのが合理的です。理由は、このイベントが呼び出される時期が、AnimTree が作成され初期化された後だからです。この種の特殊な初期化を行うために、多数のイベントが提供されています。特別な初期化機能を PostBeginPlay() イベントに追加する前に、このようなイベントが提供されていないか、まず確かめてみるべきでしょう。

event PostBeginPlay()

プレイヤーの作成

プレイヤーの作成は、ログインプロセスを通じて、ゲームタイプ (例 : GameInfo クラス) の内部で処理されます。ネットワーク オンライン マルチプレイヤー ゲームの場合、このような考え方は非常に合理的です。「Unreal」では、オンライン / オフライン、マルチプレイヤー / シングルプレイヤーに左右されず、上記と同じ基本プロセスが利用されます。(ただし、オンラインでは、当然のことながらこれ以上の動作が実行されることになります)。

ログインプロセスは、次のようにいくつかの段階に分けることができます。

  • PreLogin
  • Login
  • PostLogin

PreLogin() イベントは、ネイティブコードから呼び出され、プレイヤーがゲームに参加できるか否かを決定する処理を担当します。このイベントは、ゲームタイプの AccessControl オブジェクトを使用し、その PreLogin() 関数を呼び出すことによって、プレイヤーが参加できるか否かを決定します。

event PreLogin(string Options, string Address, out string ErrorMessage)

Login() イベントは、ネイティブコードから呼び出され、プレイヤーをスポーンする処理を担当します。新たなプレイヤーを作成するために必要となる特別な機能は、ここに追加することができます。

event PlayerController Login(string Portal, string Options, const UniqueNetID UniqueID, out string ErrorMessage)

PostLogin() は、プレイヤーがゲームへの参加に成功した後で、ネイティブコードから呼び出されます。このイベントは、プレイヤーの初期化を行うのに適しています。また、ここから PlayerController にある複製された関数を安全に呼び出すことができます。

event PostLogin( PlayerController NewPlayer )

マッチの開始

実際のゲーム (プレイヤーがスポーンしてからゲームが終わるまで行われるゲームプレイ) は、マッチ (match) としばしば呼ばれます。 これは単なる用語であって、「Unreal Engine 3」によって作成されるゲームの種類とは関係がありません。

マッチが開始されるのは、 PostLogin() イベントから StartMatch() 関数が呼び出されたときです。(この関数は、他にも、 PendingMatch ステートにおいて、 StartMatch()StartArbitratedMatch() からも呼び出されます)。この関数は、プレイヤーの Pawn をスポーンする処理を担当するとともに、マッチが開始したことを全プレイヤーに通知する処理を担当します。

function StartMatch()

実際に、プレイヤーの Pawn をスポーンするのは RestartPlayer() 関数です。この関数は、 StartHumans() および StartBots() 関数から呼び出されます。さらに、この 2 つの関数は、 StartMatch() から呼び出されます。この関数は、 Pawn をスポーンさせる他にも、プレイヤーがゲームを始める開始地点 (例 : PlayerStart) を定めます。

function RestartPlayer(Controller NewPlayer)

ゲームの終了


ゲームタイプは、ゲームが終了したか否かを決定する処理を担当します。ただし、一定の間隔で行われたり、エンジンによって開始されたりする自動的なチェックではありません。重要なイベントが起きたときにゲームタイプに通知することによって、そのイベントがゲームの終了に結びつくかどうかをゲームタイプにチェックさせるのは、ゲームに関係するアクタの役割です。このようなチェックは通常 GameInfo のサブクラスに追加された特別な関数の中で実行されます。たとえば、 UTGame ゲームタイプには、 CheckScore() 関数があります。この関数は、プレイヤーが殺された場合はいつでも呼び出され、殺されたことによってゲームを終了すべきか否かを判断します。このような関数のどれかが、ゲームの終了を判断すると、その関数は、 EndGame() 関数を呼び出します。この EndGame() は、さらに CheckEndGame() を呼び出します。これらの関数が、ゲームを終了できると判断し、さらに、現在のゲームタイプを終了させるアクションを実行するのです。

アドベンチャー ロールプレイング ゲームの例では、プレイヤーがダンジョンでボスキャラを倒すか、あるいは目標を達成すると、ボスキャラ (あるいは目標) がゲームタイプに対して、自身が殺された (達成された) ことを通知します。すると、ゲームタイプが、すべてのゲーム終了条件がクリアされたかどうかを確かめます。ゲームの終了条件が実際にクリアされていたら、ゲームタイプは、 EndGame() を呼び出すことによって、ゲーム終了のための適切なアクションを実行します。すなわち、プレイヤーをメインのワールドに戻すとともに、何らかの方法でダンジョンが完遂されたことを記録するのです。メインのワールドでは、ゲームタイプが、プレイヤーの進行状況 (この場合は、プレイヤーによってダンジョンが完遂されたこと) をロードするとともに、さらに、すべてのゲーム終了条件が満たされたかどうかをチェックします。条件が満たされていたるならば、ゲームタイプは、 EndGame() を呼び出すことによって、ゲームの終了に適切なアクションを開始します。

もちろん、以上は単なる例であり、あらゆるゲームにはさまざまなルールやフロー、ゲーム終了条件があります。しかし、考え方はいずれのゲームでも明確です。