AchievementSystem 2.0

Unreal Engine 向けの、モジュール式で柔軟な実績システム。UI やセーブ処理を強制せず、実績とカテゴリを管理するためのクリーンなコアを提供します。


はじめに

AchievementSystem は、実績とカテゴリを管理するためのクリーンなコアを提供します。UI やセーブ処理は一切強制されないため、すべてを自分でコントロールできます。すべてのデータはデータテーブル(Data Table)から読み込まれるため、ローカライズや効率的なスケーリングが可能です。

データテーブル駆動名前・説明・アイコンはデータテーブルに格納され、ローカライズにすぐ対応できます。
2階層のカテゴリトップレベルカテゴリがカテゴリを含み、カテゴリが実績を含みます。
進捗の追跡各実績は進捗と最大進捗を持ち、自動的に達成判定されます。
UI にすぐ使えるデータ読み取り専用の構造化された関数を、そのままウィジェットに接続できます。
マルチプレイ対応オンラインや複数プロフィールのゲーム向けに、プレイヤーごとのシステム参照を利用できます。
追加マクロFor Each With Delay と Get All Data Table Items を同梱しています。

システムの仕組み

システムはシンプルなデータフローを中心に構築されています。

  1. 定義
    実績とカテゴリはデータテーブルで定義され、実行時にプリロードされます。
  2. セーブとロード
    実績の保存方法と読み込み方法は開発者が制御し、その後、すでに解除済みの実績をシステムに伝えます。
  3. 活用
    ロード後、システムは実績をカテゴリ別に整理し、UI やゲームプレイのロジックでそのまま使える構造化データを提供します。

導入手順

  1. 子ブループリントを作成
    BP_AchievementsSystem を開き、子ブループリントクラス(Child Blueprint Class)を作成します。この子ブループリントが、メインの実績システムのインスタンスになります。
  2. 構造体を作成
    実績データを保持する構造体(Structure)を作成します。ID(整数)と Max Progress(整数)を必ず含めてください。
  3. データテーブルを作成
    データテーブルを作成し、先ほどの構造体を割り当てます。実績データ(名前、説明、アイコンなど)を入力してください。
  4. イベントグラフを開く
    BP_Achievements_Child を開き、イベントグラフ(Event Graph)に移動します。
  5. Preload Achievement Data を追加
    関数 Preload Achievement Data を追加します。3つの値が必要です(下の表を参照)。
  6. 値を接続
    プリロードしたい各実績について、必要な値をすべて接続します。
入力説明
ID実績の一意の識別子。
Max Progress実績の達成に必要な最大進捗値。
Row Nameデータテーブル内の、この実績の行名。
サンプルが必要ですか? デモの AchievementStyle_01 を参照してください。

カテゴリの概要

カテゴリシステムは、2階層のみのシンプルなツリー構造です。トップレベルカテゴリ(Top Level Categories)と実績カテゴリ(Achievement Categories)の2つです。これにより、システムは分かりやすく効率的になります。

トップレベルカテゴリ 01
├─ カテゴリ 01
│   ├─ 実績
│   └─ 実績
└─ カテゴリ 02
    ├─ 実績
    └─ 実績

実績カテゴリのプリロード

どの実績がどのカテゴリに属するかを定義するには、Preload Achievement Category を使用します。実績のプリロードと同じ方法で動作します。

入力説明
Category IDカテゴリの一意の識別子。
Achievement IDs(Array)このカテゴリに属するすべての実績 ID。
Row Nameカテゴリ用データテーブル内の、このカテゴリの行名。

トップレベルカテゴリのプリロード

トップレベルカテゴリは、複数のカテゴリをまとめます。Preload Top Level Category を使用します。

入力説明
Category IDトップレベルカテゴリの一意の識別子。
Category IDs(Array)このトップレベルカテゴリに属するすべてのカテゴリ ID。
Row Nameデータテーブル内の、このトップレベルカテゴリの行名。

簡単な例

進行(トップレベルカテゴリ 01)
├─ ストーリー(カテゴリ 01)
│   ├─ 最初の一歩
│   └─ 新たな始まり
└─ 探索(カテゴリ 02)
    ├─ 最初の発見
    └─ 探索の達人

スキル(トップレベルカテゴリ 02)
├─ 一般スキル(カテゴリ 01)
│   └─ 完璧な実行
└─ 精密さ(カテゴリ 02)
    ├─ ワンショットの妙技
    └─ ぶれない手

関数リファレンス

注意:これらの関数は読み取り専用で、データを変更しません(Achievement Trigger を除く)。

達成済み実績(Complete Achievements)

以下の3つの関数は、同じ構造体を返します。

関数入力説明
Get All Completed Achievementsなしシステム内のすべての実績の全体進捗。統計、UI、プレイヤーへのフィードバックに使用します。
Get All Completed Achievements By CategoryCategory ID特定のカテゴリ内の進捗。カテゴリの進捗を UI に表示する場合や、カテゴリがすべて達成されたかを確認する場合に使用します。
Get Completed Achievements In Top Level CategoryCategory ID(トップレベル)トップレベルカテゴリ内(すべてのサブカテゴリを含む)の進捗。複数のカテゴリをまとめた進捗を表示する場合に使用します。

ロード(Load)

実績のロード関数は、次の項目を持つ構造体の配列を返します:Row Name、Complete Date(String)、Progress(Int)、Max Progress(Int)、Is Completed(Bool)。

関数入力出力 / 用途
Load Achievements By CategoryCategory IDカテゴリ内のすべての実績。1つのカテゴリ用の UI を構築する場合に使用します。
Load All Achievementsなしすべての実績を一度に取得します。全体の統計やゲーム終了時のサマリーに使用します。
Load All CategoriesなしID と Row を持つ構造体の配列。カテゴリ一覧の作成や、カテゴリ単位の処理に使用します。
Load Child CategoriesCategory ID(親 / トップレベル)各子カテゴリの ID と Row。トップレベルカテゴリ内のサブカテゴリを表示する場合に使用します。
Load Top Level CategoriesなしRow、Category ID、Category IDs(子カテゴリの配列)を持つ構造体の配列。すべてのトップレベルカテゴリとそのサブカテゴリを表示する場合に使用します。

ステート(States)

3つとも Pure 関数です。

関数入力出力用途
Get ProgressAchievement ID (Int)Progress (Int)、Max Progress (Int)1つの実績の進捗を表示または確認します。
Get Row NameAchievement ID (Int)Row Name (Name)実績のローカライズ済みデータ(名前、説明、アイコン)を取得します。
Is Completed ?Achievement ID (Int)Return Value (Bool)ゲームプレイのロジックや UI 更新のために、達成状態を確認します。

Achievement Trigger

指定したプレイヤーについて、特定の実績の進捗をトリガーし、更新します。

入力説明
Achievement ID (Int)トリガーする実績の ID。
Player Ref (Actor)実績をトリガーしたプレイヤーへの参照。

用途:実績に関連するアクション(討伐、収集、探索、インタラクトなど)をプレイヤーが行うたびに呼び出します。

Get Achievement Data

デフォルトの Achievement System インスタンスを検索し、その参照を返します。

Get Achievement Data By Reference

特定のプレイヤーに紐づく Achievement System を返します。これにより、プレイヤーごとに独立した実績データを持てます。

アーキテクチャに関する重要な注意

このシステムの関数は、Achievement Trigger を除き、内部的にすべて Get Achievement Data の上に構築されています。つまり、これらの関数には次の特徴があります。

マルチプレイ / オンラインゲームに関する注意

オンラインまたはマルチプレイのゲームを開発している場合、ゲームプレイのロジックにこれらの関数を使用しないでください。進捗、達成済み実績、カテゴリの表示など、UI のみで使用してください。

プレイヤー専用の Achievement System 参照を使用するには:

  1. BP_AchievementFunctions を開きます。
  2. 使用したい関数を探します。
  3. その関数を複製(Duplicate)します。
  4. 複製した関数が Get Achievement Data By Reference を使用するように変更します。
  5. 関数に Player Reference 入力を追加します。

これにより、プレイヤーごとの実績データと、マルチプレイに安全なロジックを完全にコントロールできます。

Achievement Trigger が異なる理由

Achievement Trigger は Get Achievement Data に依存しません。実績 ID とプレイヤー参照を必要とするため、ゲームプレイのロジックに安全で、マルチプレイに対応し、開発者が完全に制御できます。

プレイヤー不在のマップに関する注意

プレイヤーやキャラクターが存在しないレベルでは、実績システムはデフォルトでは動作しません。これを解決するには、BP_AchievementsWorld をレベルに追加し、そのプロパティを設定します。

プロパティ説明
Achievement Class使用する実績コンポーネントを選択します(例:BP_AchievementStyle_01)。
EAchievement Date Format達成日の日付形式(例:USA、MM/DD/YYYY)。
Use Category Optimized Loadingカテゴリ単位の最適化ロードを有効にします。
Auto Load Categoryカテゴリの自動ロードを有効にします。

これにより、メインメニュー、ログイン画面、その他のプレイヤー不在のマップでも、システムが正しく動作します。

追加ツール

For Each With Delay (Macro)

通常の For Each Loop と同じように動作しますが、各反復の間に遅延を追加します。

ピン説明
Arrayループ対象の配列。
Duration (Float)各要素を処理する間隔(デフォルトは 0.05)。
Loop Body、Array Element、Array Index、Completed標準の For Each Loop と同じ動作です。

UI 要素や実績、その他の配列データを、ゲームをフリーズさせずに順次ロードするのに便利です。

Get All Data Table Items (Macro)

複数のノードを書かずに、データテーブルのすべての行を取得します。

ピン説明
Table (input)読み取りたいデータテーブル。
Loop Body各行に対して実行されます。Array Element / Out Row は現在の項目の行構造体です。
Row Not Found行が存在しない場合にトリガーされます。
Completedすべての行の処理が終わった後にトリガーされます。

データテーブルを、クリーンかつ効率的に素早く反復処理するのに便利です。