UDN
Search public documentation:

GameCenterJP
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 ホーム > Mobile HomeJP > Unreal Engine 3: モバイル概要 > Unreal Engine 3: Apple iOS 概要 > Game Center
UE3 ホーム > ネットワーク & レプリケーション > Game Center

Game Center(ゲームセンター)


概要


Game Center は、Apple 社のオンラインゲームネットワークです。このネットワークを使用することによって、ユーザー同士で、接続、比較、競うことができます。「Unreal Engine 3」を使用して iOS デバイスのために開発されたゲームは、Game Center を使用することができるため、特別でコミュニティ主導のエクスペリエンスを提供することができます。

ALERT! 注記 : 以下のセクションで、GC と書かれている場合は、Game Center のことを指します。

ALERT! 注意 : UnrealScript 内から直接 OnlineSubsystemGameCenter を参照 しない ようにすることは重要です。PC 上で UDK を起動しようとすると問題が生じるからです。常に、OnlineSubsystem の参照を利用するようにしてください。プラットフォームに応じて、「Unreal Engine 3」が自動的に正しい型の OnlineSubsystem を使用します。

コンフィギュレーションの設定


GC は、iOS 版「Unreal Engine 3」によってサポートされています。これには、OnlineSubsystemGameCenter クラスを使用します。ただし、起動時に Login / Welcome back 画面が自動的に呼び出されるので、コンフィギュレーションファイルによって GC を有効 / 無効にすることができます。GC のテストを開発中に行う必要がない場合には、次のようにして、変数に true をセットすることができます。必要な場合には、false をセットします。

.\UDKGame\Config\IPhone\IPhoneEngine.ini
[OnlineSubsystemGameCenter.OnlineSubsystemGameCenter]
bDisableGameCenter=true ; false

achievement (成績) 機能とleader board (順位表) 機能を使用する予定がある場合は、成績と順位表の識別子すべてに使用されるプレフィックスを設定する必要があります。Apple は、achievement および leader board を識別する上で、それらに付けられたグローバルに一意な文字列名を利用するため、あなたがすでにもっている一意の アプリケーション / バンドル識別子をその文字列名の土台として使用するのが良いでしょう。

UDKGame\Config\IPhone\IPhoneEngine.ini
[OnlineSubsystemGameCenter.OnlineSubsystemGameCenter]
bDisableGameCenter=true ; false
UniqueAchievementPrefix=com.epicgames.exploreue3.achievement_
UniqueCategoryPrefix=com.epicgames.exploreue3.leaderboard_
EpicUniqueAchievementPrefix=com.epicgames.exploreue3.achievement_
EpicUniqueCategoryPrefix=com.epicgames.exploreue3.leaderboard_

iTunes Connect を利用して achievement および leader board のカテゴリを作成する場合は、指定したプレフィックスから始まるように名前を設定し、01、02、03 ... をそれぞれの名前に付け加えます。 (achievement one をロック解除すると、コードによって 01 が UniqueAchievementPrefix に追加されます)。

OnlineSubsystemGameCenter のコンパイル


「Unreal Engine 3」は OnlineSubsystemGameCenter をプリコンパイルしてくれません。これは、ゲームに Game Center を使用されることが想定されていないためです。 OnlineSubsystemGameCenter をコンパイルするには、DefaultEngine.ini にある EditPackages のリストに追加する必要があります。

UDKGame\Config\DefaultEngine.ini
[UnrealEd.EditorEngine]
+EditPackages=UTGame
+EditPackages=UTGameContent
+EditPackages=OnlineSubsystemGameCenter

EditPackages リストへの追加を完了したら、次にUnrealscript のソースコードをコンパイルします。 OnlineSubsystemGameCenter パッケージが UDKGame\Script フォルダに表示されるようになります。 UnrealScript のコンパイルに関する詳細については、 このページ? を参照してください。

achievement (成績)


Achievement.png

achievement は他のプラットフォームとほぼ同じように機能します。ただし、GC では、初めて achievement のロック解除を行ったときに、オンスクリーンでメッセージが表示されません。ゲームコードによって achievement のロック解除を試みる場合は、まず、achievemnt がユーザーのためにまだロック解除されていないことを確認する必要があります。一般的なフローは次のようになります。

  • ゲームを起動します。(1 度実行する必要があります。ただし、それ以上実行しても問題はありません)。
    • OnlineSub.PlayerInterface.AddReadAchievementsCompleteDelegate() を呼び出して、achievementのデータの読み取りが完了した通知を受けます。
    • OnlineSub.PlayerInterface.ReadAchievements() を呼び出して、achievement を読み取り始めます。
    • デリゲートの中では、achievement がすでに読み込まれているため、この時点で achievement のステートをクエリすることができます。
  • プレイヤーがゲームをプレイし、achievement の基準を満たします。
    • OnlineSub.PlayerInterface.GetAchievements() を呼び出して、すべての achievement のステートを取得します。
    • 返された配列から識別子が一致する achievement を探します。
      • achievement の識別子を achievement の配列に入れる添字として使用 しないで ください。なぜなら、achievement ID では配列のインデックスが 1 から始まるからです。(UnrealScript や他の多くの言語では、配列のインデックスが 0 から始まります)。
    • bWasAchievedOnline が false の場合。
      • UI の表示や音楽の再生などをします。
      • OnlineSub.PlayerInterface.UnlockAchievement() を呼び出して、プレイヤーが achievement をロック解除したことを GC に通知します。

ロック解除した achievement をプレイヤー自身が確認できるようにするには、自作の UI ( OnlineSub.PlayerInterface.GetAchievements() の結果を利用します) を使用するか、あるいは、GC に備わっているスクリーンを表示します。このためには、 OnlineSub.PlayerInterfaceEx.ShowAchievementsUI() を呼び出すだけで、GC の UI がスクリーン上に滑り込むように表示されます。

achievement の技術的詳細事項

GC のコードは、起動すると即座に achievement のダウンロードを開始します。したがって、ゲームのコードが実行される時までには、ダウンロードは完了しているはずです。しかし、安全を期すために、デリゲートを使って OnlineSub.PlayerInterface.ReadAchievements() 呼び出しを行うことによって、achievement のダウンロードが完了したことを確認するとともに、 OnlineSub.PlayerInterface.GetAchievements() が正しい値を返すことを確認するべきです。

内部的にはかなり複雑なプロセスが achievement について実行されています。achievement がロック解除されたときにユーザーがオフラインであった場合、GC はサーバーに通知しません。そのため、iOS デバイスのフラッシュディスクに保存されるローカルの achievement に関するステートを保守します。ユーザーが後で GC に接続した場合は、必ず、エンジンがリモートの achievement のステートとローカルの achievements のステートに相違がないかチェックするとともに、両者をマージし、UI を表示することなく achievements をロック解除します。

ALERT! 注意: achievement の ID が -1 にセットされている場合は、achievement が適切にダウンロードされなかったか、あるいは、UniqueAchievementPrefix と EpicUniqueAchievementPrefix のいずれかまたは両方が適切に設定されなかったかのどちらかです。

achievement の例

本例では、achievement のハンドラ アクタ クラスが作成されることによって、achievement の呼び出しを転送できるようにしています。 もちろん、他のクラス (例 : GameInfo クラス) に移すことも可能です。achievement ハンドラの機能は、ペンディングしている achievement リストを保存する (複数の achievement が矢継ぎ早に得られた場合に備えて) とともに、非同期の関数を呼び出すことによって、ペンディングしているすべての achievement がロック解除されるまでそれらの間でループさせるというものです。

achievement をロック解除するには、achievement id をパラメータとして、YourAchievementHandler::UnlockAchievement() を呼び出します。この achievement id は、achievement id の末尾の数と一致していなければなりません。たとえば、 com.epicgames.exploreue3.achievement_01 という id をもつ achievement であれば、1 という achievement id をもつことになります。なお、achievement id は、通常、0 からではなく 1 から始まることに注意してください。

最初のチェックは、achievement id がペンディング中の achievement 配列に入っていることの確認です。これによって、achievement が複数回ロック解除されることを防ぎます。achievement ハンドラが現在 achievement を処理していない場合は、ペンディング中となっている achievement の処理を開始するとともに、ProcessingAchievements フラグを true にセットします。これによって、非同期の achievement 処理ループが開始されます。

ここから、achievement がサーバーから読み込まれたときに呼び出されるデリゲートが割り当てられるとともに、achievement を読み込むための非同期の呼び出しが実行されます。

YourAchievementHandler.uc
class YourAchievementHandler extends Actor;

// Pending achievements
var array<int> PendingAchievements;
// True if we're currently processing achievements
var bool ProcessingAchievements;

/**
 * Unlocks an achievement for the player
 *
 * @param    AchievementId      Which achievement to unlock
 * @param    LocalUserNum      Local user index
 */
function UnlockAchievement(int AchievementId)
{
  local OnlineSubsystem OnlineSubsystem;
  local int PlayerControllerId;

  // This achievement is already pending, and is in progress so just wait
  if (PendingAchievements.Find(AchievementId) != INDEX_NONE)
  {
    return;
  }

  // Add the achievement id to the pending list
  PendingAchievements.AddItem(AchievementId);

  // If we're not processing achievements right now, process one now
  if (!ProcessingAchievements)
  {
    // Connect to GameCenter and link up the achievement delegates
    OnlineSubsystem = class'GameEngine'.static.GetOnlineSubsystem();
    if (OnlineSubsystem != None && OnlineSubsystem.PlayerInterface != None)
    {
      // Grab the local player controller id
      PlayerControllerId = GetALocalPlayerControllerId();

      // Assign the read achievements delegate
      OnlineSubsystem.PlayerInterface.AddReadAchievementsCompleteDelegate(PlayerControllerId, InternalOnReadAchievementsComplete);

      // Read all achievements
      OnlineSubsystem.PlayerInterface.ReadAchievements(PlayerControllerId);

      // set true, to prevent this from being fired off again
      ProcessingAchievements = true;
    }
  }
}

この関数は、ローカルのプレイヤーコントローラ id を返す単純なヘルパー関数です。

YourAchievementHandler.uc
/**
 * Returns a local player controller id. Same rules apply to Actor::GetALocalPlayerController().
 *
 * @return    Returns a local player controller id
 */
function int GetALocalPlayerControllerId()
{
  local PlayerController PlayerController;
  local LocalPlayer LocalPlayer;

  // Get the local player controller
  PlayerController = GetALocalPlayerController();
  if (PlayerController == None)
  {
    return INDEX_NONE;
  }

  // Get the local player information
  LocalPlayer = LocalPlayer(PlayerController.Player);
  if (LocalPlayer == None)
  {
    return INDEX_NONE;
  }

  return LocalPlayer.ControllerId;
}

achievement のデータが Game Center から読み込まれると、YourAchievementHandler::InternalOnReadAchievementsComplete() が呼び出されます。まず、DownloadedAchievements 配列を初期化することによって、データが含まれていないようにするとともに、PlayerInterface::GetAchievements() を呼び出すことによって、最近ダウンロードされた achievement データを DownloadedAchievements 配列に格納します。

これより、最初にペンディング中であった achievement id をキーとして使用することによって、高速な配列インデックスの検索を実行することができます。オンラインで achievement が達成されなかった場合は、achievement がロック解除されたときに呼び出されるデリゲートがセットされ、PlayerInterface::UnlockAchievement() が呼び出されます。これによって、Game Center を介して achievement をロック解除する非同期のリクエストが開始されます。さらに、読み込み済み achievement のデリゲートが削除されることによって、ガーベジコレクションが適切に実行されます。

YourAchievementHandler.uc
class YourAchievementHandler extends Actor;

// Array of all downloads achievements
var array<AchievementDetails> DownloadedAchievements;

/**
 * Called when the async achievements read has completed
 *
 * @param    TitleId      The title id that the read was for (0 means current title)
 */
function InternalOnReadAchievementsComplete(int TitleId)
{
  local OnlineSubsystem OnlineSubsystem;
  local int AchievementIndex, PlayerControllerId;

  // Ensure we have an online subsystem, and an associated player interface
  OnlineSubsystem = class'GameEngine'.static.GetOnlineSubsystem();
  if (OnlineSubsystem == None || OnlineSubsystem.PlayerInterface == None)
  {
    return;
  }

  // Grab the local player controller id
  PlayerControllerId = GetALocalPlayerControllerId();

  // Clear the currently downloaded achievements array as we're copying the fresh data
  DownloadedAchievements.Remove(0, DownloadedAchievements.Length);

  // Read the achievements into the downloaded achievements array
  OnlineSubsystem.PlayerInterface.GetAchievements(PlayerControllerId, DownloadedAchievements, TitleId);

  // Grab all of the achievements
  if (DownloadedAchievements.Length > 0 && PendingAchievements.Length > 0)
  {
    // Grab the achievement index
    AchievementIndex = DownloadedAchievements.Find('Id', PendingAchievements[0]);

    // Unlock the achievement
    if (AchievementIndex != INDEX_NONE && !DownloadedAchievements[AchievementIndex].bWasAchievedOnline)
    {
      // Assign the unlock achievement complete delegate
      OnlineSubsystem.AddUnlockAchievementCompleteDelegate(PlayerControllerId, InternalOnUnlockAchievementComplete);

      // Start the unlocking process
      OnlineSubsystem.PlayerInterface.UnlockAchievement(PlayerControllerId, PendingAchievements[0]);
    }
  }

  // Remove the delegate reference so that garbage collection can occur
  OnlineSubsystem.PlayerInterface.ClearReadAchievementsCompleteDelegate(PlayerControllerId, InternalOnReadAchievementsComplete);
}

Game Center から、achievement がロック解除されたという返信があると、YourAchievementHandler::InternalOnUnlockAchievementComplete() が、すでにデリゲートに割り当てられているため、呼び出されることになります。ここにおいて、GUI 上に何らかのものを表示するか、サウンドを再生することによって、achievement が解除されたことを示すことになります。この後、achievement id は、PendingAchievements 配列からポップオフされます。ロック解除されるべき achievement が PendingAchievements 配列にさらにある場合は、このプロセスが再びループします。もうない場合は、使用されていたデリゲートが削除され、ProcessingAchievements フラグが false にセットされます。

YourAchievementHandler.uc
class YourAchievementHandler extends Actor;

/**
 * Called when the achievement unlocking has completed
 *
 * @param bWasSuccessful true if the async action completed without error, false if there was an error
 */
function InternalOnUnlockAchievementComplete(bool bWasSuccessful)
{
  local OnlineSubsystem OnlineSubsystem;
  local PlayerController PlayerController;
  local PlunderHUD PlunderHUD;
  local int AchievementIndex, PlayerControllerId;

  // Grab the local player controller id
  PlayerControllerId = GetALocalPlayerControllerId();

  if (bWasSuccessful && PendingAchievements.Length > 0)
  {
    // Grab the local player controller
    PlayerController = GetALocalPlayerController();
    if (PlayerController != None)
    {
      // Grab the achievement index
      AchievementIndex = DownloadedAchievements.Find('Id', PendingAchievements[0]);

      // Show the achievement on the user interface players
    }
  }

  // Pop the processed achievement regardless of whether it succeeded or not
  PendingAchievements.Remove(0, 1);

  // Ensure we have an online subsystem, and an associated player interface
  OnlineSubsystem = class'GameEngine'.static.GetOnlineSubsystem();
  if (OnlineSubsystem == None || OnlineSubsystem.PlayerInterface == None)
  {
    return;
  }

  // If we still have pending achievements left, process the next one
  if (PendingAchievements.Length > 0)
  {
    // Connect to GameCenter and link up the achievement delegates
    // Assign the read achievements delegate
    OnlineSubsystem.PlayerInterface.AddReadAchievementsCompleteDelegate(PlayerControllerId, InternalOnReadAchievementsComplete);

    // Read all achievements
    OnlineSubsystem.PlayerInterface.ReadAchievements(PlayerControllerId);
  }
  else // Otherwise, we're finished so clean up
  {
    // Clear the delegate bind
    OnlineSubsystem.ClearUnlockAchievementCompleteDelegate(PlayerControllerId, InternalOnUnlockAchievementComplete);

    // Set the flag to state that we're no longer processing achievements
    ProcessingAchievements = false;
  }
}

最後に、すべてのデリゲートの参照を確実に解除することが重要です。さもなければ、ガーベジコレクションが適切に行われなくなります。

YourAchievementHandler.uc
class YourAchievementHandler extends Actor;

/**
 * Called when the actor is destroyed
 */
event Destroyed()
{
  local OnlineSubsystem OnlineSubsystem;
  local int PlayerControllerId;

  Super.Destroyed();

  // Ensure we have an online subsystem, and an associated player interface
  OnlineSubsystem = class'GameEngine'.static.GetOnlineSubsystem();
  if (OnlineSubsystem == None || OnlineSubsystem.PlayerInterface == None)
  {
    return;
  }

  // If we're still processing achievements, delegates assigned must be clear so that garbage collection can occur
  if (ProcessingAchievements)
  {
    // Grab the local player controller id
    PlayerControllerId = GetALocalPlayerControllerId();

    // Remove the delegate reference so that garbage collection can occur
    OnlineSubsystem.PlayerInterface.ClearReadAchievementsCompleteDelegate(PlayerControllerId, InternalOnReadAchievementsComplete);

    // Clear the delegate bind
    OnlineSubsystem.ClearUnlockAchievementCompleteDelegate(PlayerControllerId, InternalOnUnlockAchievementComplete);
  }
}

leader board (順位表)


Leaderboard.png

GC には leader board というもう 1 つ大きな特色があります。これも、他のプラットフォームと同じような機能が備わっています。ただし、GC の leader board にはいくつか制限があります。GC は、複数の「カテゴリ」をともなった 1 つの「leader board」しかサポートしていません。当社では、leader board 1 つについて、複数のカテゴリを表のコラムとして扱っています。しかし、iOS の UI ではすべてのカテゴリが同一の形式とラベルで表示されるため、すべてのカテゴリが時間であったり、整数の得点であったり、撃墜数であったりします。さらに、それらは昇順か降順のどちらかになります。このことはゲームのスコアを設定する際に影響します。

スコアをリポートするには、 OnlineStatsWrite のサブクラスを作成して、そのプロパティ (1 から始まる ID (識別子) を伴う) を defaultproperties の中で設定します。そこから、オブジェクトのインスタンスを作成し、値をセットし、 OnlineSub.StatsInterface.WriteOnlineStats() を使ってレポートします。

YourOnlineStatsWrite.uc
defaultproperties
{
  Properties=((PropertyId=PROPERTY_KILLS,Data=(Type=SDT_Int32,Value1=0)),(PropertyId=PROPERTY_LEVEL,Data=(Type=SDT_Int32,Value1=0)),(PropertyId=PROPERTY_GOLD,Data=(Type=SDT_Int32,Value1=0)))
}

GC ではインクリメントする leader board がサポートされていないため、スコア (例 : 倒した数) をインクリメントする場合は、プレイヤーの倒した数をディスクに保存するか、あるいは、現在のスコアを読み込みインクリメントしてからスコアを書き出します。スコアの読み込みには、 OnlineSub.StatsInterface.ReadOnlineStats() 関数を使用します。

スコアを表示するには、自作の UI ( OnlineSub.PlayerInterface.ReadOnlineStatsForFriends() または OnlineSub.PlayerInterface.ReadOnlineStatsByRank()OnlineSub.PlayerInterface.ReadOnlineStatsByRankAroundPlayer() を利用します) を使用するか、あるいは、GC に備わっている UI を次のようにして呼び出します。

   OnlineSuppliedUIInterface(OnlineSub.GetNamedInterface('SuppliedUI')).ShowOnlineStatsUI();

スコアの読み取りを行う関数はすべて OnlineStatsRead のサブクラスを必要とします。まず独自にサブクラスを作成して、defaultproperties 内で ColumnIds の設定を行います。さらに、このオブジェクトのインスタンスを作成するとともに、そのインスタンスを ReadOnlineStats() 、および、 ReadOnlineStatsForFriends()ReadOnlineStatsByRank()ReadOnlineStatsByRankAroundPlayer()ShowOnlineStatsUI() 関数に渡します。複数列からなる複数行を読み込むには、最初の列に基づいて行がソートされることになります。(これは、後にランキングの列を作るために変更される場合があります)。achievement の読み取り同様、オンラインのステート読み取り完了時に関する、イベントベースのシステムを使用すべき場合があります。(これには、 AddReadOnlineStatsCompleteDelegate() を使用してデリゲートを呼び出します)。

YourOnlineStatsRead.uc
defaultproperties
{
  ColumnIds=(PROPERTY_KILLS,PROPERTY_LEVEL,PROPERTY_GOLD)
}

leader board の技術的詳細事項

achievement の場合と同様に、ユーザーがオフライン中にスコアがリポートされた場合は、GC によってスコアが自動的に再送信されることはありません。したがって、内部では多くの処理を行いつつ、最高スコアと最低スコアをディスクに保存することになります。さらに、ユーザーが次回サインインしたときに両スコアをサーバーにレポートすることになります。leader board が昇順であるのか降順であるのかを判断することができないため、最高スコアと最低スコアが必要となります。

統計値を読み込み、すべてのスコアを QWORD / Int64 (9,223,372,036,854,775,808 から 9,223,372,036,854,775,807 までの 64 ビットの整数値) として (GC が leader board の値を保存するやり方です) リポートします。

マルチプレイヤー


現在、マルチプレイヤー機能にはロビーベースのマッチメイクのみがサポートされています。最大人数は 4 人です。GC は GKMatch オブジェクトを使ってネットワークトラフィックを処理します。そのため、ゲームネットワークのための通信対象となれるのは GC のマッチメイクで見つかったプレイヤーに限定されます。4 機の iOS デバイスのうち 1 機がサーバーの役目を受け持ちます。

Matchmaking (マッチメイク)

マッチメイクは GC に備わっているインターフェースを利用して実行されます。

   OnlineSuppliedUIInterface(OnlineSub.GetNamedInterface('SuppliedUI')).ShowMatchmakingUI();

ALERT! 注意 : ShowMatchmakingUI() 関数に渡される GameSettings オブジェクトは、現在使用されていません。None になる可能性があります。

現在のところサーバーになるプレイヤーを選択することはできません。各プレイヤーがマッチメイクモードに入り、その内 1 人がサーバーとして選ばれ、残りのプレイヤーがクライアントとなります。(一定のプレイヤーの集まりにおいて、同一のプレイヤーがサーバーになり続けます。どのプレイヤーをサーバーにするかを決定する際には、各プレイヤーがもっている一意の識別子が使われます。したがって、各デバイスは余計な通信を行うことなくクライアントであるのかサーバーであるのかを認識することができます)。

プレイヤーがサーバーであるのかクライアントであるのかに応じて、マッチメイク完了後に 2 つのデリゲートから 1 つが呼び出されます。サーバーの場合は、 OnCreateOnlineGameComplete デリゲートが呼び出されます。クライアントの場合は、 OnJoinOnlineGameComplete デリゲートが呼び出されます。両方の場合を処理するために、ゲームにおいては両方のデリゲートを登録します。

Join (すなわちクライアントサイド) のデリゲートでは、 OnlineSub.GameInterface.GetResolvedConnectString(SessionName,URL) 関数を使用することによって、サーバーに移動する ( ClientTravel(URL, TRAVEL_Absolute) を使用します) ための URL を取得することができます。

ALERT! 重要 : 招待 (下記事項参照) を受けた場合は、 PlayerController のコードによって、Join デリゲートが追加され、当該 URL に移動します。 PlayerController.uc ファイルの OnInviteJoinComplete() 関数を参照してください。このため、ユーザーがマッチメイクモードに入る選択をしたときは、Join デリゲートの登録だけで済みます。

Create (すなわちサーバーサイド) のデリゲートでは、通常 ClientTravel(SomeURL, TRAVEL_Absolute) 関数と同じような処理を行うことによってマップをロードします。クライアントはサーバー接続情報を持つとともに、接続 URL を開くことによってサーバーに参加します。このデリゲートが使用されるのは、ユーザーがマッチメイクモードに入るか、あるいは、招待を受け入れてサーバーに選ばれた場合です。したがって、Create デリゲートは常に登録しておく必要があります。

招待

GC では、マッチメイク UI からプレイヤーを招待できる機能がサポートされています。招待されたプレイヤーが異なるゲームをプレイしていた場合は、招待メッセージが表示されます。招待を受け入れる場合は、当該のゲームが起動します。また、ゲームが起動するとともに、GC のマッチメイクの UI が上方にスライドしていくため、プレイヤーは自分がゲームに参加しているということを知らされます。

招待されたプレイヤーがすでに当該ゲームをプレイしている場合は、 PlayerController のコード ( OnGameInviteAccepted() 参照) によって現在のオンラインゲームが破棄されます。さらに、GC のマッチメイク UI が表示されるため、プレイヤーは自分がゲームに参加しているということを知らされます。なお、招待されたプレイヤーがサーバーになることもあります。

ボイスチャット

GC には非常に基本的で使いやすいボイスチャットシステムがサポートされています。マルチプレイヤー型ゲームに入ると、 OnlineSub.VoiceInterface.StartNetworkedVoice() 関数が呼び出され、プレイヤーがお互いと話すことができるようになります。消音機能および会話中のプレイヤーを検索する機能もついています。その場合、標準の関数である MuteRemoteTalker()IsRemotePlayerTalking() などが使われます。

ダウンロード


  • YourAchievementHandler.uc - Achievement 例のためのソースコードをダウンロードすることができます。