Unity用 ノード型クエスト・イベント管理システムアセット "Quest Progression System"
- ダウンロード商品¥ 400


■ クエストシステムの実装は、なぜ毎回こんなに大変なのか 「敵を10体倒す」だけなら簡単です。 ですが実際に作り始めると、こうなります。 ・「ステージ1のボスに2回勝利かつ 金貨を300集める」という複合条件が欲しい ・敵を1種類追加するたびに、クエスト側の判定コードも書き足すことになった ・デイリー任務を実装したら、アプリを閉じている間に日付が変わってリセットされない ・前のクエストをクリアすると次が解放される「任務ツリー」を後から足したくなった ・進捗をセーブに乗せたいが、クエスト用に別のセーブファイルは増やしたくない ・クエストログUIは自分のゲームのデザインで作りたい このアセットは、その全部を引き受けます。 ゲーム側が書くのは 1 行だけです。 quests.Report("enemy.defeated", "slime"); どのクエストがこれを数えるかは、クエストアセット側の条件が決めます。 つまり クエストを100件追加しても、この通知コードは1行も増えません。 同梱の実演シーンは、メニュー1クリックで構築 → 再生ボタンを押すだけで、 全機能が18ステップの字幕付きで自動再生されます。 画面内で時計を進めるので、デイリー任務が翌日リセットされるところまでその場で見られます。 ■ 作れるクエスト(すべてインスペクタ入力・コード不要) 【達成条件】 ・スライムを3体倒す … 対象IDで指定 ・アンデッドを5体倒す … タグ指定(敵IDを列挙しなくてよい) ・アンデッド以外を5体倒す … 除外タグ ・金貨を合計300枚集める … 数量の合計 ・最大コンボ25に到達する … 最大値の到達 ・1-4 をボス戦かつS勝利で2回 … ランク下限+状況フラグ 【条件の結合】 ・All … 全条件を満たすと達成(AND) ・Any … いずれか1つで達成(OR) ・AtLeast … 3つのうち2つ以上で達成 【周回とリセット】 ・1度限り/無限周回/1日3回まで(回数上限つき周回) ・デイリー(毎日5時更新)/ウィークリー(月曜更新)/マンスリー/6時間ごと ・ローカル時間基準・UTC基準(世界同時更新)を選択可能 【解放ツリー】 ・前提クエストをクリアすると解放。分岐ルート(どちらかをクリアで解放)も可 ・未解放クエストは進捗を積まないので、先の任務が勝手に進むことがない ・隠しクエスト(解放されるまで一覧に出ない) 【編成条件】 ・「主人公をリーダーに、回復役と魔法使いを入れたちょうど3人編成」 ・1人が2枠を兼任しないよう解決するので、指名キャラが汎用枠に吸われる事故が起きません ■ リセットは「タイマー」ではありません デイリー任務でよくある実装ミスが、経過時間タイマーです。 アプリを閉じている間は時間が進まないため、日付が変わってもリセットされません。 本アセットは「今が属する周期の開始時刻」を求め、セーブされた値と違えばリセットする方式です。 3か月ぶりに起動しても、デイリーは1回だけ・ウィークリーも1回だけ、正しくリセットされます。 ■ セーブもUIも、既存のものをそのまま使えます 購入をためらう最大の理由は「今あるセーブ機構やUIを作り直すことになるのでは」だと思います。 そうはなりません。 【セーブ】 保存先は差し替え式です。PlayerPrefs・JSONファイルの実装を同梱していますが、 最も多いのは「自分のセーブデータに埋め込む」形です。 // セーブ時 mySaveData.questJson = store.ToJson(); // ロード時 store.LoadFromJson(mySaveData.questJson); 進捗データは public フィールドのみで構成しているので、JsonUtility でも自作シリアライザでも扱えます。 一度も進捗が動いていないクエストはレコードを作らないため、数百件追加してもセーブは太りません。 【UI】 UIプレハブは同梱していません。クエストログの見た目はゲームの個性そのもので、 既製UIはほぼ確実に作り直しになるからです。 代わりに、UIが欲しがる値を全て計算して返します。 var s = quests.GetSnapshot(quest); gauge.fillAmount = s.Ratio; // 0〜1 countText.text = QuestProgressFormatter.FormatProgress(s); // "3 / 5" claimButton.SetActive(s.IsClaimable); resetText.text = QuestProgressFormatter.FormatTimeUntilReset(s); // "5h 12m" 任務ツリー画面も、座標計算だけを提供しています(描画方法は自由です)。 var graph = QuestTreeLayout.Build(quests.GetQuests("story", includeLocked: true)); foreach (var node in graph.Nodes) Instantiate(nodePrefab, content).anchoredPosition = node.Position; 【独自ルール】 データで表現しきれない条件は、アセットを改造せずに差し込めます。 quests.EventFilter = (quest, evt) => !IsDuplicateKill(evt) && IsEventPeriod(); サーバー時刻を正にしたい場合は IQuestClock を実装するだけです(端末時計を進める不正対策)。 ■ 導入は3ステップ 1) Project → Create → UnitForge → Quest でクエストを作る(インスペクタ入力のみ) 2) メニューからレジストリを作成する(以後クエストは自動収集。手作業のドラッグは不要) 3) 初期化して通知する var quests = new QuestService(QuestRegistry.LoadDefault(), new PlayerPrefsQuestProgressStore()); quests.RewardHandler = myInventory; // 報酬の付与先(あなたのインベントリ) quests.Report("enemy.defeated", "slime"); ■ 動作確認メニューを同梱しています Tools → UnitForge → Quests → Run Self-Test (動作確認) あなたのUnityバージョン・プラットフォーム設定で正しく動くかを、その場で検証して結果を出力します。 検証はすべてメモリ上で行われ、プロジェクトにアセットもセーブデータも作りません。 導入直後、Unityのバージョン更新後、自分で拡張したあとの確認にお使いください。 ■ 動作環境 ・Unity 2022.3 LTS 以降 ・追加パッケージ不要(純粋なUnityのみ/DOTween等のプラグイン不要) ・Input System はどちらの設定でも動作します(入力を一切使いません) ・2D/3D、URP/HDRP/ビルトイン、いずれでも動作します(描画に関与しないため) ■ 収録内容 ・Runtime 一式(フルソース・アセンブリ定義で分離) ・エディタ拡張(クエスト用インスペクタ/条件の折りたたみ表示/行動キーのドロップダウン/ レジストリ自動収集とビルド直前の自動焼き込み) ・実演シーン(メニュー1クリックで構築・18ステップ自動再生・削除可) ・最小構成のサンプル4種(初期化/報酬付与/クエストログUI/編成通知) ・動作確認メニュー(自己診断) ・日本語+英語のドキュメント(README・XMLコメント・インスペクタのツールチップすべて日英併記) ■ FAQ・制限事項(正直に記載します) Q. UIプレハブは入っていますか? A. 入っていません(上記の理由)。表示に必要な値は全てAPIから取得できます。 実演シーンのクエストログは動く実装例として読めます。 Q. オンラインゲームで使えますか? A. 進捗の正当性検証はサーバー側の責任になります。 IQuestClock と IQuestProgressStore を差し替えることで組み込めます。 Q. ローカライズは? A. ローカライズ機構は含みません。クエスト名・説明は文字列なので、 既存の手法(Unity Localization 等)で差し替えてください。 Q. 編成条件は複数部隊にまたがって判定できますか? A. 1回の判定は1つのパーティが対象です。部隊ごとに通知を呼び分けてください。 Q. 既存のクエストシステムから移行できますか? A. 進捗データの構造が単純(クエストID・条件別カウント・状態)なので、 旧データからの変換スクリプトを書く形で移行できます。 ■ ライセンス 購入者本人および購入者が所属する組織での、商用・非商用を問わないゲーム開発にご利用いただけます。 ソースコードの改変は自由です。アセット自体の再配布・再販売はご遠慮ください。

