数字の向こうに国が見えた頃――昔の光栄ゲームと今作りたいSLG

昔の光栄ゲームが好きだった。

ここで言う「昔」というのは、だいたい2000年より前の光栄ゲームのことだ。

『信長の野望』や『三國志』のような歴史シミュレーションを中心に、『提督の決断』『大航海時代』『チンギスハーン』『ロイヤルブラッド』など、当時の光栄は今振り返ってもかなり幅広いシミュレーションゲームを出していたと思う。

そして私は、それらをかなり繰り返し遊んだ。

今の基準で見れば、決して派手なゲームではなかったかもしれない。
画面いっぱいに数字が並ぶ。
武将の能力値、兵士数、金、米、忠誠、訓練、友好度、都市の状態、艦隊、交易品、名声。
人によっては「表計算ソフトみたい」と感じるかもしれない。
けれど、私はそこにワクワクしていた。

数字の向こうに国があり、武将がいて、戦争があり、外交があり、世界があった。

■ 繰り返し遊んだ光栄ゲームたち

昔の光栄ゲームは、本当にいろいろ遊んだ。

まず『信長の野望』。
一番遊んだのは『信長の野望・烈風伝』だと思う。
続いて『信長の野望・将星録』、そして『信長の野望・武将風雲録』。
『烈風伝』は特に、全国マップの上で城や勢力が動いている感覚が強く、何度も繰り返し遊んだ記憶がある。

国を少しずつ広げていく。
武将を集める。
内政を整える。
隣国の動きを見ながら、次にどこを攻めるかを考える。

その積み重ねがとても楽しかった。
『将星録』や『武将風雲録』も含めて、やはり『信長の野望』シリーズには、国取りSLGとしての強い魅力があったと思う。

次に『三國志』シリーズ。
こちらは『三國志III』を最も遊んだ。
続いて『三國志II』『三國志IV』『三國志V』の順だと思う。
『三國志III』は、当時かなり繰り返し遊んだ。
武将の能力値を眺め、都市の状態を見て、誰をどこに置くかを考える。
強い武将だけを集めれば良いというわけではなく、微妙な能力の武将にも役割を与えながら国を動かしていく感じが好きだった。

数字を見ているだけで、次にやることが頭の中に浮かんでくる。
そういうゲームだった。

『提督の決断』では、『提督の決断III』を死ぬほど繰り返しプレイした。
題材としては太平洋戦争なので、かなり重いテーマではある。
ただ、戦略シミュレーションとして見ると、艦隊運用、戦線管理、資源、作戦の組み立てなど、考えることが非常に多かった。
この「考えることが多すぎる感じ」も、当時の光栄ゲームらしさだったと思う。

すぐに分かる面白さではない。
けれど、分かってくると延々と遊んでしまう。
『提督の決断III』には、そういう中毒性があった。

『大航海時代』では、『大航海時代II』が一番好きだった。
交易、冒険、海戦、世界を巡る自由さ。
歴史SLGとは少し違うが、世界が広がっていく感覚がとても良かった。
港を巡り、交易品を運び、冒険を進め、時には戦う。
国取りとは違う形で、世界地図を眺める楽しさがあった。
次点では『大航海時代III』も印象に残っている。
ただ、こちらは少し難しすぎた。
面白いのだけれど、かなり人を選ぶゲームだったと思う。
それでも、あの挑戦的な作りは強く記憶に残っている。

『チンギスハーン 蒼き狼と白き牝鹿IV』も繰り返し遊んだ。
とにかく世界が広い。
東アジアだけではなく、ユーラシア全体を舞台にしているようなスケール感があり、「世界を相手にしている」感覚があった。
日本や中国だけではなく、遠く離れた地域まで含めた広大な世界。
この広さは、他の歴史SLGとはまた違う魅力だった。
マップを見ているだけで楽しい。

次はどこへ進むのか。
どの地域を押さえるのか。
どこに敵がいるのか。

そういうことを考えるだけで、かなり時間が過ぎていった。

そして最後に、『ロイヤルブラッドII 〜ディナール王国年代記〜』。
これは個人的に、相当好きな部類のゲームだ。
歴史ものではなく、ファンタジー世界を舞台にした戦略シミュレーション。
国があり、人物がいて、世界があり、その中で勢力を動かしていく。
大作RPGでもなく、派手なアクションでもなく、キャラクターを前面に押し出すゲームでもない。
ファンタジー世界を舞台にした、骨太な戦略SLG。
こういうゲームは、今では本当に出なくなったと思う。

私が今作っている『王国創世記 -Kingdom Chronicle-』にも、このあたりの影響はかなりある。

■ 昔の光栄ゲームは、決して万人向けではなかった

昔の光栄ゲームは、決して万人向けではなかったと思う。

説明不足な部分もある。
画面も派手ではない。
演出も控えめ。
操作も、今のゲームほど親切ではない。

そして値段もやたら高かった(笑)

けれど、その分だけプレイヤーが想像する余地が大きかった。
数値とテキストと顔グラフィックだけで、こちらは勝手に物語を作っていた。
この武将は能力は低いけれど、長年仕えてくれているから使い続けたい。
隣国とは今戦いたくないから、しばらく同盟しておこう。
この都市は兵糧が少ないから、長期戦に持ち込めば勝てるかもしれない。
忠誠が低い武将がいるから、引き抜けるかもしれない。
ゲーム側がすべてを演出してくれるわけではない。
むしろ、かなりの部分をプレイヤーの想像力に委ねていた。

私はそこが好きだった。

■ 面倒くさいから面白かった

昔の歴史SLGや戦略SLGには、面倒くささがあった。

国ごとに命令を出す。
武将ごとに役割を考える。
都市の数字を見比べる。
隣国との関係を見る。
兵力を確認する。
忠誠を気にする。
外交を考える。

今のゲームなら、もっと自動化される部分も多いと思う。
けれど、その面倒くささこそが面白かった。
プレイヤーが手を入れた分だけ、国が少しずつ強くなっていく。
よく考えずに動けば、外交で孤立したり、兵糧が尽きたり、武将が離反したりする。
派手なアクションではなく、盤面と数字の積み重ねで遊ぶゲームだった。

そして、そういうゲームはかなり人を選ぶ。

万人向けではない。
チュートリアルで気持ちよく遊ばせるタイプでもない。
見た目だけで面白さが伝わるゲームでもない。

でも、刺さる人には深く刺さる。

昔の光栄ゲームには、そういう強さがあったと思う。

■ いつからか、光栄ゲームを買わなくなった

ところが、いつからか私は光栄、そして現在のコーエーテクモのゲームをあまり買わなくなった。

全く買わないわけではない。
気になるタイトルがないわけでもない。
ただ、かつてのように「これは絶対に遊びたい」と思うことが減っていった。

理由はいくつかあるが、一番大きいのは、ゲームの方向性が変わっていったように感じたからだ。
もちろん、会社として大衆向けに作るのは正しい。

ゲーム開発にはお金がかかる。
売れなければ続かない。
分かりやすく、見栄えよく、広い層に届くゲームにしていくのは当然の判断だと思う。

むしろ、企業としてはそちらの方が正しい。

ただ、その一方で、自分が好きだった「画面いっぱいの数字と、複雑な判断を楽しむゲーム」は、だんだん主流から外れていったようにも感じる。

大衆向けになるほど、分かりやすさが求められる。
テンポの良さも必要になる。
見た目の派手さも必要になる。
キャラクター性や演出も、昔よりずっと重視される。

その流れ自体は否定できない。

けれど、その中で、昔の光栄ゲームにあったような、少し不親切で、少し面倒で、でも延々と考えていられるSLGは作りにくくなったのだと思う。

■ 今、大手メーカーが作りにくいSLG

今の大手メーカーが、昔のような骨太なSLGを作りにくいのは分かる。
開発費は上がり、ゲームに求められる見た目の水準も上がった。
分かりやすさ、テンポの良さ、派手さ、キャラクター性。

そういうものが重視されるのは当然だと思う。

画面いっぱいに数字が並び、プレイヤーがそれを眺めながら国の行く末を考えるようなゲームは、たぶん今の大作市場では売りにくい。

かなり人を選ぶ。
すぐに面白さが伝わるタイプでもない。
動画映えもしにくい。
チュートリアルで全員を気持ちよく導けるゲームでもない。

だから、大手メーカーがそういう方向に行きにくいのは理解できる。
売上が立たなければ、継続して作ることはできない。

会社である以上、それは当然だ。

ただ、それでも私はそういうSLGが好きだった。
内政をして、武将を集めて、同盟を結んで、裏切って、攻め込んで、国を少しずつ広げていく。
数字として表示されるだけの友好度や忠誠や兵力に、勝手に物語を感じる。
派手な演出がなくても、頭の中ではいろいろなドラマが起きている。

そういうゲームが、今でも好きだ。

■ 牧歌的で、骨太で、少し古いSLG

昔の光栄ゲームには、どこか牧歌的な良さがあったと思う。

もちろん、ゲームの題材は戦争だったり、国盗りだったり、決して牧歌的な内容ばかりではない。

それでも、プレイ感としては、どこかのんびりしていた。

ターンを進める。
数字を見る。
内政する。
武将を配置する。
外交する。
戦争の準備をする。

すぐに反射神経を求められるわけではない。
派手なコンボを決めるわけでもない。
自分のペースで盤面を眺めて、考えて、少しずつ国を動かしていく。

そういう時間があった。
今の時代に、そのまま昔のゲームを再現しても通用しないとは思う。

UIは見やすくしたい。
操作も分かりやすくしたい。
演出もある程度は必要だと思う。
テンポも悪すぎてはいけない。

けれど、根っこにある楽しさは残したい。

数字を見て考える楽しさ。
国を育てる楽しさ。
武将に愛着を持つ楽しさ。
勢力同士の関係が少しずつ変わっていく楽しさ。
自分だけの戦史が生まれていく楽しさ。

そういうSLGを作りたい。

■ だから、自分で作りたい

今、自分で『王国創世記 -Kingdom Chronicle-』という戦略SLGを作っている。

これは歴史SLGそのものではない。
舞台は中世風のファンタジー世界で、実在の武将や歴史上の国家が登場するわけではない。
けれど、根っこの部分では、昔の光栄ゲームから受けた影響がかなり大きいと思う。

国を動かす楽しさ。
武将の能力値を眺める楽しさ。
勢力間の外交関係を見る楽しさ。
忠誠や友好度の数字に意味を持たせる楽しさ。
地図を眺めながら、次にどこへ攻めるかを考える楽しさ。

そういうものを、自分なりにもう一度作ってみたい。

昔の光栄ゲームそのものを再現したいわけではない。
今の時代に合わせて、見た目も操作性も整えたい。

ただ、あの頃に感じていた、

「数字の向こうに国が見える」
「武将の能力値を眺めているだけで楽しい」
「世界地図を見ながら次の一手を考える」

という感覚は、自分の中にかなり強く残っている。

『王国創世記』にも、たぶんそれがにじみ出ていると思う。

■ 刺さる人には刺さるゲームを作りたい

大衆向けではないかもしれない。
派手なゲームでもないかもしれない。
今の主流から見れば、少し古いゲームに見えるかもしれない。

けれど、刺さる人には刺さる。

昔の光栄ゲームには、そういう魅力があった。
画面いっぱいの数字を見て、面白そうだと思える人。
武将の能力値を眺めて、配置を考えるだけで楽しい人。
地図を見ながら、次の一手を考えるのが好きな人。
国が少しずつ広がっていくのを見るのが好きな人。

そういう人に届くSLGを作りたい。

今の大手メーカーがなかなか作らないなら、個人開発だからこそ作ってもいいのではないかと思っている。
売れ筋から外れていてもいい。
少し面倒でもいい。
分かる人にだけ深く刺さるゲームでもいい。
むしろ、そういうゲームを作れるのが個人開発の良さなのかもしれない。

少し古くて、少し面倒で、でもずっと遊んでいられるようなSLG。
数字の向こうに国が見えるようなSLG。

そんなゲームを作りたいと思っている。

『王国創世記 -Kingdom Chronicle-』は、たぶんその思いから始まっている。

【開発[#2] 38日目】戦略SLG

今回は37日目〜38日目の作業まとめになります。

この2日間は、AIの外交判断、謀略コマンド「引抜」、外交コマンド「破棄」など、勢力間の駆け引きに関わる処理を中心に進めました。また、演出面では季節エフェクトの本体連結も行い、開発運用そのものの見直しにも着手しています。
地味な内部処理が多めですが、戦略SLGとしてはかなり重要な土台部分です。

■ 37日目:AI外交コマンド「同盟/親睦」の本実装

37日目は、AI思考ルーチンに外交コマンド「同盟」と「親睦」の判断・発行ロジックを実装しました。

対象となるのは、AIコマンド入力フェーズの外交処理です。いきなりコードを書くのではなく、まずは仕様をかなり細かく確認しました。その過程で、当初のフローに到達不能な分岐、いわゆるデッドコードのようなものがあることが分かりました。
こういう部分は、後で無理にコードだけ整えようとすると高確率で破綻するので、先に仕様側を整理しています。

■ AI外交判断を四段構造に再設計

最終的に、AIの外交判断は大きく4段階の流れに整理しました。
まず、同盟相手や同盟可能勢力の中に、信頼度40以上の相手がいなければ親睦を優先します。成功率の低い同盟要請を無理に出すのではなく、まずは関係改善を狙う形です。
次に、同盟数を見て同盟行動へ進むかどうかを判断します。同盟数が0なら同盟行動を優先し、すでに1つ同盟がある場合は一定確率で同盟を狙う、という流れです。

親睦を行う場合は、同盟の有無によって対象候補や閾値を切り替えます。
同盟を行う場合は、同盟可能勢力の中から「同盟優先度数」を使って候補を抽選し、相手の信頼度に応じて同盟か親睦かを分岐させます。

文章にすると少しややこしいですが、要するに、

・味方がいないなら同盟を狙う
・信用できる相手がいないなら親睦する
・同盟しすぎて戦争相手がいなくなる状態は避ける
・状況に応じて、外交と戦争の余地を両方残す

という思想です。

■ 同盟可能条件の整理

同盟可能な相手の条件も明確化しました。
今回の実装では、以下の条件をすべて満たす勢力だけを同盟候補にしています。

・相手の同盟数が2未満であること
・同盟しても出陣先、つまり非同盟の隣接勢力が残ること
・同盟しても全生存勢力と同盟関係にならないこと

特に重要なのは、同盟によってAIが動けなくなる状況を防ぐことです。
戦略SLGでは、外交が強すぎると盤面が止まってしまうことがあります。
逆に、外交が弱すぎると同盟や親睦が空気になります。
今回はその中間を取るために、「同盟はするが、戦争できる余地は残す」という制約を入れています。

■ 同盟優先度数の導入

同盟候補の抽選には、単純なランダムではなく「同盟優先度数」を使う形にしました。
同盟優先度数は、友好度をベースにしつつ、非隣接勢力や名声の低い勢力に補正を加えています。隣接勢力だけと同盟し続けると、戦争対象が減ってしまいやすいため、非隣接勢力に少し加点(遠交近攻)しています。また、名声が低い勢力は外交面でやや同盟を求めやすい、という扱いです。

このあたりは、数字としては地味ですが、AIの行動傾向をかなり左右する部分だと思います。

■ AIは信頼度を全参照する仕様に

信頼度については、本来プレイヤー側では諜報力60以上で参照可能になる情報です。
ただし、AIは判断材料として信頼度を全参照する仕様にしました。

いわゆるAI特権です。

プレイヤーに見えない情報をAIが見るのは少しズルく見える部分もありますが、AIが外交判断をするためには、ある程度情報を持っていないと自然な動きになりません。
プレイヤー側はマスク表示、AI側は判断材料として参照、という形で割り切っています。ただAIは諜報力維持行動の優先度が高いので諜報力0とかになることは基本的にないようAI調整してます。大体50~60は最低限維持するようなAI行動パターンです。

■ 37日目の成果

実装としては、ManagerPhase.cs に AssignDiplomacy と関連ヘルパーを追加しました。36日目に整備した拠点所有データも、隣接判定の土台として活用しています。これにより、AIが同盟・親睦コマンドを判断し、発行するところまで動くようになりました。
ただし、現時点では同盟や親睦の「締結処理」や「友好度変動」は、まだ数値変動フェーズ側が未実装です。
つまり、AIが外交コマンドを出すところまではできていますが、その結果を実際に反映する部分は後日実装となります。
中間状態ではありますが、段階的な実装としては予定通りです。

■ 38日目:季節エフェクト、引抜、破棄、開発運用の見直し

38日目は、複数の作業をまとめて進めました。
大きく分けると、

・季節エフェクトの本体連結と是正
・謀略コマンド「引抜」の数値処理
・外交コマンド「破棄」の決済処理
・開発運用の見直し

の4つです。
この日は見た目の演出と、内部の数値処理の両方を触っています。

■ 季節エフェクトの連結是正

まず、季節エフェクトを本体コードへ連結しました。
これは、四季に応じて画面上に舞い落ちるパーティクルと、画面端のグラデーションを出す演出です。
春・夏・秋・冬で画面の雰囲気を変えるためのものです。
今回の季節エフェクトは、独立性の高い演出部分として別AIに作らせ、その後で本体コードへ連結・是正するという流れで進めました。

この開発フローは今回が初回運用です。
切り出せる演出系は別AIで作成し、本体担当側では連結と調整に集中する、という形です。うまく回れば、かなり開発効率が上がりそうです。

■ 季節判定ロジックを GameUtility に集約

連結時に確認したところ、季節算出ロジックが複数箇所に重複していました。
このままだと、後で季節の仕様を変えたときに、どこかだけ修正漏れする危険があります。
そこで、季節算出ロジックは GameUtility に集約しました。
季節が変わっても1箇所を直せばよい構造になったので、保守性はかなり改善されたと思います。
また、グラデーション用マテリアルの破棄処理も追加し、メモリリーク対策も行いました。
文字エンコードの混在チェック、季節列挙型の統合、不要になった独立ファイルの削除も実施しています。
シェーダについても、プロジェクト規約である Built-in RP 準拠、Shader Graph 不使用で問題ないことを確認しました。
最終的に、演出側の季節判定式と本体側のゲーム処理の季節判定が一致していることも確認しています。

これで、「画面演出上は春なのに、ゲーム処理上は夏」みたいな事故は避けられるはずです。

わかりにくいかもしれないが秋には紅葉や枯れ葉がひらひらと舞う


■ 謀略コマンド「引抜」の数値処理を実装

次に、謀略コマンド「引抜」の結果処理を実装しました。
これは他勢力の武将を引き抜くコマンドです。
今回実装したのは、コマンド実行後の結果処理、つまり数値変動フェーズ側の処理です。
ここも、仕様の矛盾や不明点を整理してからコード化しています。

引抜の結果は、

・完全成功
・部分成功
・失敗

の3パターンに分かれます。
1回の乱数でこの3分岐を判定する形です。

■ 引抜の完全成功・部分成功・失敗

完全成功した場合、対象武将は相手勢力から出奔します。
発覚した場合は、相手勢力との友好度が下がります。
引き抜いた武将は一度在野へ放流され、プレイヤー側であれば登用判断へ、AI側であれば空席があれば即登用する形です。部分成功の場合は、対象武将の忠誠が下がります。
さらに、対象以外の配下にも巻き添えで忠誠下落が発生する可能性があります。ただし、配下人数が多いほど巻き込まれにくくなるように、傾斜確率を入れています。
失敗した場合は、相手勢力との友好度が下がり、さらに実行武将の捕縛判定が発生します。このあたりは、謀略コマンドらしくリスクとリターンが出るようにしています。
適用特技としては、明晰・英傑による知力補正、篭絡による完全成功率上昇、潜伏逃亡による捕縛回避などを反映しました。

■ 登用UIは後日実装

完全成功時の登用UIについては、今回はまだ実装していません。
これは満席時の入替UIに依存するためです。
枠だけ残して、後日その周辺のUIとあわせて実装する予定です。
こういう部分は無理に仮実装すると後で作り直しになりやすいので、今回は処理本体を優先しました。

■ 外交コマンド「破棄」の決済処理を実装

続いて、外交コマンド「破棄」の処理を実装しました。
これは同盟を破棄するコマンドです。
処理場所は、数値変動フェーズの外交処理段階になります。
破棄は相手に拒否されず、100%成立する決済として扱います。

実装内容としては、

・双方の同盟状態を解消
・双方の友好度を下落
・破棄した勢力の名声を下落
・関連特技による補正を適用

という形です。
同盟破棄は便利な行動ですが、ノーリスクだと強すぎます。
そのため、友好度と名声の両方にペナルティが入るようにしています。
適用特技としては、明晰・求心・英傑による能力補正、無才によるペナルティ最小化を反映しています。

また、名声の変動処理も1箇所に集約しました。
今後、名声が上がる処理を追加する場合も、同じ処理を通す方針です。
地味ですが、後で効く整理です。

■ 即時破棄ペナルティは将来実装

仕様上、「敵勢力の同盟勝利が迫った際の即時破棄」には大きなペナルティを入れる想定があります。
ただし、この処理は勝敗判定ロジック自体に依存します。現時点では勝敗判定ロジックが未実装のため、今回は将来の実装項目として残しました。
こういう依存関係のある処理は、先に無理やり作るより、土台ができてから入れた方が安全です。

■ 開発運用の見直し

最後に、開発運用そのものも見直しました。
最近はAIを併用しながら開発を進めていますが、長い作業を続けていると、チャットや引き継ぎ情報が肥大化しがちです。

そこで、チャットの区切り方を見直しました。
これまでは日付単位で区切る意識がありましたが、今後は「1タスクが完結し、次の作業が独立するタイミング」を基準にします。議論が続いているなら、日をまたいでも同じ流れで扱います。一方で、ブログや広報用の日次区切りは、チャット内の区切り対話マーカーで担保する形にします。
これにより、開発作業としての区切りと、ブログ記事化の区切りを分けられるようになります。

■ 引き継ぎドキュメントも2層構造へ

引き継ぎドキュメントも見直しました。

今後は、

・常設コア
・作業状態

の2層構造に分けます。
常設コアには、滅多に変わらないルールや仕様を置きます。
作業状態には、今まさに進行中のタスクや一時的な情報を置きます。
完了済みタスクの細かい経緯は基本的に破棄し、そこから派生した恒久ルールだけをコアへ昇格させます。
これにより、引き継ぎ情報の肥大化を抑えられるはずです。
開発そのものだけでなく、開発を続けるための仕組みも整えていく段階に入ってきた感じがあります。

■ 現時点の開発状況

今回の作業で、勢力間の駆け引きに関わる処理がかなり前進しました。
AI思考ルーチンの外交判断、謀略「引抜」、外交「破棄」と、戦略SLGらしい内部処理が増えてきています。
数値変動フェーズについては、残る大きなものがAI外交判断まわりに絞られてきました。
AIコマンド入力フェーズの通常処理も、ほぼ完成に近づいています。
一方で、出陣・援軍系については、戦争解決フェーズに依存する部分が大きいため、今後はそのあたりが大きな山になりそうです。

■ 次回の作業予定

次回以降は、今回残した外交結果の反映や、戦争解決フェーズに関わる処理を進めていく予定です。特に、出陣・援軍系の処理はゲームの中核に関わるため、仕様を整理しながら慎重に進めたいところです。
また、季節エフェクトについては、動画撮影してSNS投稿にも使えそうなので、見た目の調整も少しずつ進めていきます。内部処理と演出の両方が少しずつ揃ってきて、だいぶ戦略SLGらしい形になってきました。

引き続き『王国創世記 -Kingdom Chronicle-』の開発を進めていきます。

※2週間くらいで作るつもりでしたが、もう開発40日目が目前です(笑)

【開発[#2] 36日目】戦略SLG

■ 34〜36日目のまとめ

前回(33日目)は④結果表示フェーズの応答処理と捜索コマンドの完成、 ManagerPhaseの分離、⑦AIコマンド入力の暫定実装が中心だった。 今回はその続きとして、コマンド入力UIの残り部分を完成させ、 AI行動ロジックの拡張と、コードの基盤整備に大きく踏み込んだ3日間である。

34日目は確定パネルの勢力選択系と拠点ホバー機能の新規構築。 35日目はコマンド入力UIの最後のピースとなる出陣(March)UIの完成。 これによりCommandInterfaceの全18コマンドボタンの入力UIが出揃った。 36日目はAI行動ロジックの拡張・数値変動フェーズの穴埋め・ 拠点所有データの二重管理是正・死にコードの一掃を実施した。 地味に見えるが後で効く作業が集中した一日であった。


■ 34日目(6/1):確定パネルの勢力選択系・ホバー機能

確定パネル群 — 勢力選択系の本実装

コマンドを選んだ後に表示される「確定パネル」を整備した。 入口メソッドを「使うパネルの種類ごとに統一する」方針とし、 コマンド専用入口を量産せずに OnClickCommandXxx(type) 内での type 分岐に収めた。

同盟・破棄・計略(勢力を選ぶだけ)、親睦(資金+勢力選択)、 要請(確認のみ・出陣連動)の5コマンドが動作するようになった。 また引抜は「勢力を選ぶ → その勢力の武将を選ぶ」という2段階フローの骨組みを構築した。 武将選択パネル自体はまだ空のモックだが、フロー自体は通る状態にしている。

コマンドボタンの無効化条件も整理した。 開発(国力999)/ 同盟(2勢力同盟中)/ 破棄(同盟なし)/ 要請(同盟なし or 出陣なし)/ 計略・引抜(諜報20未満)が無効となる。

勢力選択モード — 新しい状態遷移レベルの追加

「マップ上の拠点をクリックして勢力を選ぶ」モードを新設した。 状態遷移レベル4として ViewCommandConfirm_SelectFaction を追加し、 確認パネルから100%ズームの拠点地図へ遷移する。 選択不可の勢力の拠点は暗く(黒tint)表示し、クリックで勢力を確定する。 マップの状態(ズーム・位置)は退避・復元する方式で、出陣でも引抜でも流用できる形にした。

引抜はさらに「武将を選ぶ」レベル5(ViewCommandConfirm_SelectOfficer)を追加し、 勢力選択 → 武将選択の2段階を右クリックで1段ずつ戻れる構造とした。

拠点ホバー機能

マップ上の拠点にカーソルを合わせると、同じ勢力の全拠点が点滅し、 画面左下に Panel_FactionHoverInfo(勢力情報ポップアップ)が表示されるようにした。 点滅の仕組みはタイトル前のシーンで使っていた機構をManagerMainへ移植している。

ホバー情報は諜報レベルに応じてパラメータをマスクする(Panel_FactionDetailInfoと同基準)。 友好度・信頼度の段階テキストは GameUtility.GetFriendshipStageText / GetEsteemStageText として共通化し、DiplomacySimpleInfoとPanel_FactionHoverInfoの両方が使用する。

細かいところでは、同じ勢力の複数拠点を素早くなぞったときに ホバーが取りこぼされて残留してしまう問題を、0.15秒の猶予処理で潰している。 見た目の気持ちよさの調整は、コードの正しさとは別の戦いである。


■ 35日目(6/2):出陣UIの完成 — 全18コマンドのUI出揃い

出陣(March)UI — 2段階拠点選択

出陣は「どの自拠点から出すか」「どの敵拠点を攻めるか」という 2段階の拠点選択が必要で、全コマンドの中で最も複雑な入力フローとなる。

フローは以下の通りである。 確認パネル → 出発拠点選択(Lv4)→ 目標拠点選択(Lv5)→ 兵数トグル選択 → 確定。 右クリックで1段戻ることができ、途中で選び直せる。

拠点選択ロジックは「勢力を括らない汎用判定」として設計した。 BuildOriginBastionIdsFor(factionId) のように勢力IDを引数で受ける形にすることで、 プレイヤーの出陣だけでなくAI出陣(A-2/⑦)にも同じロジックが流用できる。

設計上の重要な判断

出陣の実装で確定させた設計判断をいくつか記録しておく。

まず「兵数は出撃時に即座に引く」。 戦争は2ターンかかる仕様のため、出撃時に兵を減らしておかないと 「兵50で50出撃したのに翌ターンも50残っている」という二重出撃バグが発生する。 複数拠点同時出撃の管理も別メモリ保持では破綻する。 生き残った兵は戦争解決フェーズ(A-2)で本国へ戻す方式とした。

次に「出撃時の訓練度をコマンドに固定保存」する。 出撃後に本国で訓練や徴兵を行うと訓練度が変動するため、 戦闘計算は出撃した瞬間の値を使わなければならない。 OfficerCommandSaveData と OfficerCommand の両方に Training フィールドを追加し、 コマンド格納時の値を固定する設計にした。

兵数上限は Min(名声由来の動員可能数, 保有兵数) である。 実際に兵を引く以上、保有を超える出撃は起こり得ないためである。

接続線の状態管理機構

接続線を「論理状態」で管理する仕組みへ ConnectionLineDrawer を全面改造した。 状態(Normal / Highlighted / …)を保持するマップを内部に持ち、 見た目(色・線幅)は GetLineAppearance で状態から導出する。

DrawLines が既存ペアの状態を維持するため、ズーム再描画をしても強調が消えない。 今後 A-2 で「味方出撃・敵出撃・迎撃・援軍」を線の見た目で表現する予定であり、 場当たりで作ると確実に作り直しになる。先に仕組みから作るという判断だ。

操作案内パネル・出撃拠点パルス演出

選択操作中に「いま何を選べばいいか」を画面下端中央に表示する Panel_SelectionGuide を新設した。 文言は Panel_CommandInterface.GetSelectionGuideText に集約しており、 コマンドごとの調整は1箇所だけ変えればよい。

出発拠点はパルス演出(ゆっくりした明滅)で選択中の起点を明示する。 ホバー点滅とは別系統で実装し、競合が起きない設計とした。

まず出陣する拠点を選択する。
次に攻め込む拠点を選択する。
攻め込む勢力と出陣拠点、目標拠点がセットされる。

■ 36日目(6/3):AI拡張・数値変動の穴埋め・基盤整備

AI行動ロジック — 計略・引抜の実装

AIが実行できていなかったコマンドのうち、計略(優先9)と引抜(優先10)を実装した。

計略の対象勢力選択は「最も友好度が低い勢力を固定で狙う」方式から、 「友好度59以下の勢力から低いほど当たりやすい重み付きランダム抽選」へ変更した。 (重み = 60 − 友好度、下限1) 毎ターン同じ相手を集中攻撃して不自然になることを避けつつ、 敵対度が高い相手を優先して狙う傾向を維持する設計である。 非同盟勢力を優先し、全員が友好度60以上なら計略は不発となる。

計略と引抜は前半フロー(諜報力ゲート → 君主除外 → トリガー判定 → 対象勢力選択)が 共通しているため、 TryResolveCovertCommand としてまとめた。 入口となる TryPriority_Plot と TryPriority_Poach は各コマンド固有の処理だけを持ち、 薄く保つ構造にしている。

なお引抜については、③StatChange_Poach(数値処理本体)が未実装のため、 現時点ではAIがコマンドを発行しても数値は動かない。 ⑦のAI発行ロジックだけ先行している状態である。

AI行動仕様の是正(既存コードの修正)

AI行動仕様PDF(完全版)との照合で判明したズレ3点を是正した。

1点目は ProcessAIReward のコメント修正。 実コードは「資金50未満なら判断しない」で正しいが、 コメントが「10未満」と古い値のままだった。

2点目は開発コマンドの実行確率テーブル(RatePtsDevelop)の修正。 国力500〜998の区間が線形補間になっていたが、仕様では「フラット10%」が正しい。 (998, 0.1) のポイントを追加することで500〜998を平坦にした。

3点目は CalcAIInvestGold(AI投入資金の算出)の改修。 保有資金の半分を上限としつつ、コマンドごとに必要資金の選択肢 (施し・開発は10/20/30、徴兵は10/20/30/40/50)を持ち、 その中から半分以下で最大の額を選ぶ方式に変更した。 AIが資金を使い切らず温存しながら行動するバランスを維持する。

③数値変動フェーズの穴埋め

仕様書のメンテナンスで処理順と計算式が確定したため、2点を実装した。

1点目は <3>内政の処理順是正である。 仕様では「開発(国力↑)→ 訓練(訓練度↑)→ 徴発(民忠↓/資金↑)→ 施し(民忠↑)」の順が定められているが、 実装は順不同になっており、徴発と施しの順序が仕様と逆だった。 4パス化(ApplyDomesticPass)で明示的な処理順を保証した。 徴発で下げた民忠を施しで上げ直す順序には意味があり、 最終的な民忠の値が<4>資金収入の計算に波及するためである。

2点目は <4>資金収入の実装(StatChange_Funds)である。 収入の計算式は「国力 × (民忠 ÷ 100) × 0.5(小数点切り上げ)」で、 春(ターン順番0)と秋(ターン順番2)のみ発生する。 季節判定は (CurrentTurn – 1) % 4 で行う。 AI勢力には難易度補正を乗算する(Easy × 1.0 / Normal × 1.2 / Hard × 1.5・仮値)。

なお収入の④結果パネルへの表示は現時点では未実装である。 コマンド実行結果(CommandResultLog)とは別の「ターンイベント」系として 別の入れ物クラスで管理する方針とし、④の作り込み段階で実装する。

拠点所有データの二重管理是正 — 今日のいちばんの大仕事

拠点を「どの勢力が所有しているか」という情報が、 コードの中で以下の3箇所に重複して保持されていた。

  • FactionData.OwnedBastionIds(ランタイム勢力クラス)
  • FactionSaveData.OwnedBastionIds(セーブデータ・勢力ドリブン)
  • GameSaveSlot.BastionOwnerships(セーブデータ・拠点ドリブン)

片方の更新を忘れた瞬間にデータが矛盾するバグの温床であるため、是正した。

方針は「BastionOwnerships(拠点ドリブン)を単一の真実とする」である。 拠点が自分の所有者を知っており、勢力側は必要なときに問い合わせる構造が論理的に正しい。

手順は4段階に分けて実施した。

まず GameUtility に問い合わせ口を集約した(Step1)。

GetOwnedBastionIds(slot, factionId)  … 保有拠点IDのリストを返す
GetOwnedBastionCount(slot, factionId) … 保有拠点数を返す
GetBastionOwner(slot, bastionId)      … 拠点の所有者勢力IDを返す
SetBastionOwner(slot, bastionId, fid) … 所有者を更新する(A-2用の書き込み口)

次に OwnedBastionIds を読んでいた6箇所をヘルパー呼び出しに置換した(Step2)。 対象は ManagerPhase(配下枠アンロック)、Panel_FactionDetailInfo / Panel_FactionHoverInfo(拠点数表示)、 Panel_CommandInterface(March拠点選定・拠点数表示)である。

書き込み側を一本化し(Step3)、最後にフィールド定義を削除した(Step4)。 コンパイル・動作確認OK(マップ表示・配下枠・出陣・拠点数表示)。

FactionData 死にコードの一掃

VS の単語単位検索で FactionData クラスの参照を調査したところ、 外部参照がゼロの死にコードであることが確定した。 CreateFromScenario の呼び出し元がどこにも存在せず、型を参照する場所もなかった。

FactionRelationData は FactionSaveData.Relations の要素型であるため、 SaveDataGame.cs へ移動(論理的に正しい配置)した後、 FactionData.cs をファイルごと削除した。 GameEnumExtensions の GetName(this FactionData) 拡張メソッドも合わせて削除。 残骸ゼロとなった。


■ 現時点の開発状況

カテゴリ状況
データクラス全般✅ 完了
Scene_Initialize / Title / Start✅ 完了
Scene_Main(地図・情報パネル・コマンド入力)✅ 完了
Scene_Main(③数値変動フェーズ)✅ 本実装(引抜処理のみ未実装)
Scene_Main(④結果表示フェーズ)✅ 本実装(武将入替UIは別タスク)
Scene_Main(ManagerPhaseへの分離)✅ 完了
Scene_Main(⑦AIコマンド入力)🔲 暫定実装(内政・軍事・謀略の計略まで稼働。引抜は発行のみ)
Scene_Main(②戦争解決・戦闘計算)🔲 未実装(設計・計算モデルは確定済)
Scene_Main(外交AIコマンド)🔲 骨格のみ(案X保留)
Scene_End🔲 未着手

■ 次回の作業予定

次の最有力は「⑦優先2 同盟/親睦のAI本実装」である。 今回の拠点二重管理是正で、 隣接判定に必要な GetBastionOwner / GetOwnedBastionIds の問い合わせ口が整った。 AI仕様(同盟2未満ゲート・除外条件・友好度重み抽選・完全線形の確率分岐)も確定済みで、 いつでも着手できる状態である。

本丸の②戦争解決フェーズ(戦闘計算)は、仕様書の整合が取れてから本格的に着手する予定だ。 出陣・迎撃・援軍・AIの判断がすべてここに接続しており、 このフェーズを突破するとドミノ式に多くの機能が実装可能になる。

引抜の数値処理(③StatChange_Poach)も独立して進められるため、 こちらも近いうちに着手したい。

【開発[#2] 33日目】戦略SLG

■ 33日目のまとめ

前回(31〜32日目)は③数値変動フェーズを本実装し、コマンドが勢力の数値へ反映されるようになった。今回はその結果をプレイヤーに見せる「④結果表示フェーズ」の応答処理と、捜索コマンドの完成が中心である。

33日目は2つのセッションに分かれた。前半(その1)は結果フェーズで武将登用のYES/NO判断ができる仕組みの実装と、捜索コマンドの発見→登用→候補図鑑登録の一気通貫。
後半(その2)は大きなリファクタ(ManagerPhaseの分離)と、AIが実際にコマンドを
発行し始める⑦AIコマンド入力フェーズの暫定実装だ。最後にはAI勢力が内政・軍事の
数値を動かし、格段と戦略ゲームらしくなった。

■ 33日目(5/31)その1:結果フェーズの応答処理・捜索本実装

④結果表示フェーズ ― 応答が必要な結果を扱えるようにする

③数値変動の結果を表示するだけなら、テキストを縦に並べればよかった。しかし捜索で
発見した武将の登用可否など、「プレイヤーが判断しなければいけない結果」が存在する。
これをどう扱うかが今回の設計の核だった。

方針は「応答が必要な結果」と「応答が不要な結果」を同じスクロールビューに混在させて縦積みで表示し、前者には判断ボタンを付ける形にした。YESを押すと即座に確定し後から戻せない(武将の登用や解雇は巻き戻しのコストが高いため)。明確なNOボタンは設けず、「閉じる=保留=結果的にNO」として、確認完了ボタンを押したタイミングで未判断を一律NO扱いとした。ボタンを2つに収めるこのルール整理は地味に重要で、UI設計の
方向性がここで固まった。

実装物としては3つの新規クラスと既存パネルの改修になった。

まず ResultPendingDecision は「応答が必要な結果1件」を表すデータクラスで、
種別(登用・外交)と状態(保留・承認・却下)を持つ。YES確定時の処理本体は
持たず、コールバック経由で上位(ManagerMain)へ委譲する。パネルが処理の主体に
なってしまうことを防ぐ設計だ。

次に Panel_ResultConfirm はYES/Cancel 2ボタンの小さな確認パネル。ラベルは
動的に変更でき、パネル自体は日本語か英語かを知らない。呼び出し側が言語解決済みの
文字列を渡す方式にしたことで、将来の多言語追加に際して触る箇所がゼロになる。

そして ResultDecisionInfo が実際に結果一覧の中に混在する「判断ボタン付き部品」
である。ResultSimpleInfo(数値変動を表示するだけの部品)と対になる存在で、同じ
Listに入って縦積みされる。型混在でも動くのはGameObjectで統一しているおかげだ。

捜索(Search)の本実装 ― 発見から図鑑登録まで

③数値変動フェーズ内に、捜索コマンドの処理ブロックを追加した。

発見率は「(知力+魅力)÷200+0.2」で、最大1.0。特技「人脈」があれば+0.2が乗る。
在野武将の抽選は重み付き(重み=10-レアリティ)で、高レアほど出にくい。
以下の4つの特技が発動すると抽選結果が変わる。

  • 抜擢:在野の最高レアのみを対象として抽選
  • 審美眼:抽選結果のレアリティ+1のテーブルで再抽選(対象不在なら不発)
  • 新星発見:確定図鑑にも候補図鑑にも未登録の武将から再抽選(不在なら不発)
  • 人脈:発見率に+0.2

特技は重複して持てないため、上記は排他になる(1人の武将が「抜擢かつ審美眼」を
同時に持つことはない)。ただし「人脈持ちの武将が発見率を上げ、別の武将が抽選を
担当する」という組み合わせは設計上ありうる。現在の実装では1コマンド1武将のため
この組み合わせは起きないが、将来の仕様拡張を念頭に分離して書いてある。

発見が確定したら ResultPendingDecision にデータを積み、④で判断パネルを呼ぶ流れに
なる。YESで登用すると在野リストから削除・配下に追加・候補図鑑に登録の3点セットが
走る。候補図鑑へ登録するのは通常武将のみで、カスタム武将はint型IDが意味を持たない
ため対象外としている。

なお同一ターン内の二重発見防止のため、除外セットを全勢力共通で保持し捜索処理に
配布している。フィールドには持たせず揮発(毎ターン生成・破棄)としたのは、ターンをまたいで状態が残るリスクを避けるためだ。

結果パネルに登用ボタンを追加して武将を登用可能にした。

登用により空席が全て埋まった画像。


不具合2件の対応

実装中に不具合が2件、デバッグログによる原因特定→修正の流れで解消した。

1件目は解雇した武将が「前の武将のコマンド入力で復帰する」というもの。原因は
Panel_Commandsが内部に持つ武将リストと、解雇で操作される配下リスト本体の参照が
断絶していたことだ。解雇後にPanel_Commandsを閉じて開き直す方式(毎回配下リスト
基準で再構築)に変えて構造的に解消した。

2件目はより根深かった。「解雇後に別の武将でコマンド入力すると全員が入力済に見える」という現象で、解雇が原因と思って調べたら全く無関係の場所が壊れていた。
Panel_Commands.FindCommandのOfficerId比較が「AのIDかつBのIDの片方が一致する」というOR条件になっており、別人のコマンドに誤マッチしていたのだ。デバッグログを仕込んで「OfficerId=56の武将がOfficerId=33のコマンドにヒット」という実測値を確認してから修正した。IsCustomフラグで通常/カスタムを排他分岐し、通常武将はAND条件で厳密に一致を取るよう書き直して根治している。

■ 33日目(5/31)その2:ManagerPhase分離・AIコマンド入力暫定実装

ManagerPhaseの切り出し ― 大きなリファクタ

ここ数日の実装でManagerMain.csが2143行まで膨らんでいた。「動いているコードを
別の場所に移す」は最もデグレードを引き起こしやすい作業だが、次に控えているA-2
(戦闘計算)を安全に入れるには先に構造を整えておく必要があった。

新規クラスManagerPhaseを同一GameObjectのコンポーネントとして追加し、ターンフェーズ処理を移動した。

設計で一番大事にしたのは「所有権を論理的に正しい場所に置くこと」だ。
当初は「ManagerMainにフィールドを残したままManagerPhaseから同名プロパティで
参照する」方式も検討したが、それはコピーを無改変のままにするための逃げに過ぎない。
フェーズ専用の揮発stateはManagerPhaseが物理的に所有すべきであり、
ManagerMainは自身の領分(UI・マップ・入力)だけを持てばよい。

結果として「UIに触る3メソッドだけManagerMainのpublicメソッドへ委譲し、残り37メソッドは無改変コピー」という形に落ち着いた。デグレードリスクを書き換えた3メソッドに局所化した。TurnPhase enumはGameEnums.csへ移設し、両クラスから無改変参照できるようにしている。

ManagerMain.cs:2143行 → 1077行
ManagerPhase.cs:新規 1529行

一見増えているように見えるが、ManagerMainの行数で考えると実質半減である。

⑦AIコマンド入力フェーズ ― AIが動き始める

Phase_AICommand()はここまで「Phase_EndTurnを呼ぶだけ」というモックだった。
今回、AI行動仕様(暫定PDF)をベースに、実装済みコマンドのみを実発行する暫定方式で本実装した。

実発行するのは「③数値変動フェーズで処理が回るコマンド」に限定している。

  • 捜索 / 諜報 / 施し / 徴兵 / 募兵 / 訓練 / 開発
  • 褒賞(特1・AIコマンドとは別ループで処理)

出陣・外交・計略・引抜はロジックの骨格だけ作り、発行部分をスキップする。
「本実装時にガードを外すだけで動く」形にしてある。

AIの行動優先度はPDFに定義されている。空き枠があれば捜索(優先1)・同盟締結に
向けた外交(優先2)・諜報力の維持(優先3)、といった順番で、各数値の閾値や確率テーブルに従って判断する。確率カーブと特技序列はstaticテーブルで一元管理し、調整時はテーブルの数値を書き換えるだけにした。

武将の選択ロジックは全優先度で「特技序列>能力値」という同型のため、
PickOfficerBySkillPriorityという共通ヘルパーに集約している。

ループ構造はPDF暫定版に合わせた。優先1/2はループ外の単発(2名以上実行しない
仕様を構造で保証する)。優先3〜10は3周まで通常の確率判定でループし、それでも
未行動武将が残れば4周目は確率100%(ハード条件は維持)で割り当てを試みる。
それでも残った武将はそのターン待機となる。

実装後、プレイヤーもAIも内政しかしない平和な世界ではあるが(笑)、AI勢力の国力・兵数・資金が毎ターン変動するようになり、戦略ゲームとしての体裁が一気に整った。出陣が実装されたときの変化が楽しみである。

上の画像は1年目・夏の状態で下の画像は翌ターンの状態。
資金が20減少し、訓練度が51→72、諜報力が54→85となり、武将の忠誠度が一部上昇しているのが確認できる。AIが内政している。


潜在バグの根治・褒賞計算式の共通化

リファクタのついでに潜在バグを1件根治した。_aiCommandsがどこでもClearされて
おらず、AIがコマンドを積み始めると毎ターン累積する構造だったのだ。これまでは
AIが空だったため無害だったが、今回の実装で顕在化する前に対処した。

また、褒賞の忠誠上昇計算式をGameUtility.CalcRewardLoyaltyGainという純粋関数に抽出した。プレイヤー褒賞(ManagerMain)とAI褒賞(ManagerPhase)の両方から呼ぶことで、計算ロジックの重複をなくしている。

■ 現時点の開発状況

カテゴリ状況
データクラス全般✅ 完了
Scene_Initialize / Title / Start✅ 完了
Scene_Main(地図・情報パネル・コマンド入力)✅ 完了
Scene_Main(数値変動演出)✅ 完了
Scene_Main(フェーズ管理・骨格)✅ 完了
Scene_Main(③数値変動フェーズ)✅ 本実装
Scene_Main(④結果表示フェーズ ― 応答処理)✅ 本実装(武将入替UIは別タスク)
Scene_Main(捜索コマンド)✅ 発見→登用→候補図鑑登録まで完了
Scene_Main(ManagerPhaseへの分離)✅ 完了
Scene_Main(⑦AIコマンド入力)🔲 暫定実装(内政・軍事・人事・謀略のみ)
Scene_Main(②戦争解決・戦闘計算)🔲 未実装
Scene_Main(外交・計略・引抜コマンド)🔲 入力UI未実装
Scene_End🔲 未着手
コレクション画面・武将登録画面✅ 完成(最終調整は別途)

■ 次回の作業予定

次の本丸は②戦争解決フェーズ(戦闘計算)である。AIの行動仕様のうち出陣・迎撃・
援軍に関わる部分がこのフェーズを待って詰まっており、ここを突破するとドミノ式に
多くの機能が実装可能になる。

ただし戦闘は「画面・見せ方・演出の設計がまだ」という状態で、ロジックより先に
設計から始まる重いタスクだ。並行して、外交・計略・引抜のコマンド確定パネル(
プレイヤーが入力できる状態にするUI)を先行させるか、次回冒頭で方針を決める。

【開発[#2] 32日目】戦略SLG

■ 31〜32日目のまとめ

前回(24〜30日目)は、メインシーンを「動かす」直前までの土台を固めた期間だった。今回はいよいよ本丸であるフェーズ管理に着手し、1ターンの進行が一巡する状態まで持っていった。

31日目はフェーズ管理の骨格(モック)を組み、ターンが最初から最後まで通して回ることを確認した。32日目はそのフェーズの中身、特に③数値変動フェーズを本実装し、内政・軍事・謀略の各コマンドが実際の数値変化として結果に反映されるようにした。コマンド入力から処理、結果表示までがようやく一本の線で繋がった2日間である。


■ 31日目(5/29):フェーズ管理の骨格・状態設計の整理

フェーズ管理のモック実装

1ターンを7フェーズで構成する設計はすでに確定していたため、まずは各フェーズを空の処理(モック)として並べ、ターンが端から端まで通して進行することを優先して確認した。

新規開始時は①開始フェーズから、セーブデータのロード時は⑥コマンド入力フェーズから始まるよう分岐させている。また、1ターン目は表示すべき結果がまだ無いため、④結果表示フェーズをスキップする制御を入れた。新規開始・ロード再開のどちらでもターンが正しく進むことを確認できた。

各フェーズの処理はPhase_という接頭辞で統一し、ManagerMainの末尾にまとめて配置した。将来的には専用のクラスへ切り出す前提の置き方である。

メインシーンの状態とフェーズは別概念

ここで一つ整理が必要だった。メインシーンの「状態レベル」(パネルを開いている/いない、といったUIの状態)と、「1ターン内のフェーズ進行」は別の概念である。両者が混ざらないよう、状態を管理する列挙型の名前を役割ごとに分け、コマンド入力フェーズ用・結果表示フェーズ用にそれぞれ用意した。

ターン情報パネルの追加

現在が何年目の何の季節か(1年=春夏秋冬の4ターン)を表示するパネルを追加した。ターン開始時に上からスライドインして現在のターン情報を示す。オプションで言語を切り替えた際にも表示が追従するようにしている。


配下枠の自動拡張

拠点数に応じて配下武将の枠が増える仕様(拠点1〜3で5名、以降段階的に最大9名)を、戦争解決フェーズの末尾で判定・拡張する処理として実装した。一度広がった枠は拠点が減っても縮まないため、その管理用の値を勢力データ側へ統合する修正もあわせて行っている。


ターン終了時のリセット処理

ターンをまたいで持ち越してはいけない状態(入力済みコマンド、褒賞の1回制限フラグなど)を、所定のフェーズでまとめてリセットする処理を入れた。ターンが進んだ後にコマンドを再入力できることを確認している。

ズーム座標のバグ修正

地図のズーム時、拡大の中心がずれて画面右上方向にずれていく不具合を修正した。原因は座標系の取り違えで、変換を1か所加えることでボタンズーム・ホイールズームの両方で解消した。


■ 32日目(5/30):③数値変動フェーズ本実装・資金コマンド・演出

この日は分量が多い。順に記録する。

③数値変動フェーズの本実装

フェーズの骨格に対し、中身を入れていく作業に入った。最初に着手したのが③数値変動フェーズである。

このフェーズは、入力されたコマンド(開発・施し・徴発・徴兵・募兵・訓練・諜報)の効果を、決められた順序で勢力の数値へ反映する処理である。設計書に沿って6つの段階(諜報力の減衰→兵数の変動→内政による変動→資金収支→諜報力の上昇→計略)を順に処理する形で実装した。

処理はプレイヤー勢力もAI勢力も同じロジックで回せるよう、勢力単位の共通メソッドとして切り出している。AIのコマンドはまだ入力する仕組み(⑦フェーズ)が無いため、現時点では空の状態で安全に動作するようにしてある。

各コマンドの計算式には設計書通りに能力値や特技の補正が絡む。たとえば開発なら知力と魅力、徴兵なら武力と魅力が効き、対応する特技を持っていれば補正がかかる。特技が発動したかどうかは、1回のコマンドにつき1度だけ判定し、その結果を計算と後述の結果表示の両方で使い回すようにした。これにより「表示では発動と出ているのに計算に反映されていない」といったズレが起きないようにしている。

結果の記録(プレイヤーのみ)

③のフェーズは内部で数値を処理するだけで、プレイヤーには何が起きたか見えない。そこで、誰がどのコマンドを実行し、どの数値がいくつからいくつへ変化したかを記録する仕組みを入れた。

記録は実行前と実行後の数値をそれぞれ写し取り、その差分から「変化した項目だけ」を抽出して表示する方式とした。開発なら国力の1項目、徴兵なら兵数・訓練度・民忠の3項目、というように、コマンドによって変わる項目数が違っても同じ仕組みで扱える。記録するのはプレイヤー勢力ぶんのみで、AI勢力は記録しない(表示しないため)。

結果表示パネルへの反映

記録した結果を、結果表示パネル内のスクロールビューに1件ずつ縦に並べて表示できるようにした。1件分の表示部品を新規に作り、武将・実行したコマンド・発動した特技・数値の変化量が読めるようにしている。まだ見た目は仮で、レイアウトや文言は今後詰めていくが、「誰がどう働いたか」がプレイヤーに見える状態にはなった。

以下は、結果だけを先行して表示するよう作成した仮UIの結果パネル。
発動特技はむちゃくちゃ(笑)


資金を使うコマンドの入力フロー

開発・施し・徴兵といった資金を消費するコマンドのために、資金額を選択する確認パネルを本実装した。10刻みのトグルボタンを並べ、コマンドによって選べる上限を変えている(開発・施しは30まで、徴兵は50まで)。

所持資金で払えない額のボタンは自動で無効になり、額を選ぶまでは決定ボタンも押せない。また、すでに数値が上限に達している場合(国力が999など)は、そのコマンド自体を実行不可とした。資金は確定した時点で即座に消費する方式とし、入力した額を③フェーズの計算に使う流れにしている。


数値変動の演出と操作ロック

資金を消費したとき、数値が変わる演出(前回作ったカウント表示)を見せてからパネルを閉じるようにした。

ここで一つ問題が起きた。演出の途中で別の操作をすると、後から前の演出の「閉じる」処理が遅れて発火し、開いたばかりの別パネルが勝手に閉じてしまう現象である。当初は「演出を途中で中断する」方向で対処しようとしたが、複数の操作経路すべてで中断を仕込むのは漏れが出やすい。

最終的に「演出が終わるまで操作を一切受け付けない」方式へ切り替えた。演出中はボタン操作も、地図上の右クリックによる操作も止める。演出時間は1秒程度と短いため、待ちがストレスになるほどではないと判断した。入口を1か所で締めることで、後から処理が暴発する余地そのものを消した形である。

フェーズ外でのマップ操作を禁止

結果表示パネルでスクロールバーを操作しようとすると、背後の地図が一緒にズームしてしまう問題があった。フェーズは演出によって長さが変わるため、状態ではなくフェーズそのもので判定し、コマンド入力フェーズ以外ではマップ操作(ズーム・スクロール)を一括で受け付けないようにした。


■ 結果表示フェーズの応答処理 ― 仕様を固めた

32日目の終盤は、次に着手する④結果表示フェーズについて、設計を詰める時間に充てた。

結果表示の中には、プレイヤーの判断が必要なものがある。武将の登用可否(捜索で発見した、引き抜きに成功した、など)や、AI勢力からの同盟・親睦の要請がそれである。これらは結果の一覧の中に判断ボタン付きで表示し、押すと小さな確認パネルでYES/NOを決める形にする。

判断のルールも整理した。YESを選んだら即座に確定し、後から戻せない(武将の登用や解雇は巻き戻しのコストが高いため)。判断せずに進めた場合は一律でNO扱いとする。明確なNOボタンは設けず、「閉じる=保留=結果的にNO」で兼ねることで、ボタンを2つに収めた。満席時の入れ替えについては、武将選択のUIを別途設計してから対応する。

ここは次回の最有力の着手対象であり、仕様を固めておくことで次の作業にすぐ入れるようにした。


■ 現時点の開発状況

カテゴリ状況
データクラス全般✅ 完了
Scene_Initialize / Title / Start✅ 完了
Scene_Main(地図・情報パネル・コマンド入力)✅ 完了
Scene_Main(数値変動演出)✅ 完了
Scene_Main(フェーズ管理・骨格)✅ 実装
Scene_Main(③数値変動フェーズ)✅ 本実装
Scene_Main(資金コマンド入力フロー)✅ 完了
Scene_Main(④結果表示フェーズ)⬜ 仕様確定・実装はこれから
Scene_Main(②戦争解決・戦闘計算)⬜ 未実装
Scene_Main(⑦AIコマンド入力・AI)⬜ 未実装
Scene_End⬜ 未着手
コレクション画面・武将登録画面✅ 完成(最終調整は別途)

■ 次回の作業予定

次回は④結果表示フェーズの応答処理を実装する予定である。ただし、応答が発生する元(捜索での発見、引き抜きの成功、AIからの外交要請)がまだ実装されていないため、その発生源となる人事系または外交系のコマンドを先に作る必要がある。どちらから着手するかは次回の冒頭で整理する。

その先には、最も複雑になるであろう②戦争解決フェーズ(戦闘計算)と、⑦AIコマンド入力フェーズ(AIの行動ロジック)が控えている。コアループの骨格は動き出したので、ここから各フェーズの中身を一つずつ埋めていく段階に入る。

【開発[#2] 30日目】戦略SLG


■ 24〜30日目のまとめ

今回は7日分をまとめて記録する。

前回(23日目)でメインシーンの「見る」部分がほぼ出揃った。今回はそこから「動かす」へ向けた地ならしの期間となった。コマンド確認パネル群の実装、Panel_CommandInterfaceの本実装と仕上げ、武将・勢力情報表示の拡充、状態レベル設計の大きな見直し、数値変動演出システムの新規導入、多言語化の不具合対応、そしてコマンドボタンのデザイン適用までを進めた。

最優先課題であるフェーズ管理の本実装は次回へ持ち越しとなったが、その前に「フェーズ管理に集中できる土台」を整えることに注力した7日間だった。


■ 24日目(5/19):コマンド確認パネル群の設計確定・モック実装

確認パネルを7種に分離

コマンドを実行する前に表示する確認パネルを、入力要素の組み合わせごとに7種類へ分離する方針を確定した。1枚に共通化しようとすると無理が出る組み合わせがあり、また作業単位を細かく分けたかったためである。

  • Panel_CommandConfirm:OK/Cancelのみ
  • Panel_CommandConfirmGold:資金INPUT + OK/Cancel
  • Panel_CommandConfirmFaction:勢力SELECT + OK/Cancel
  • Panel_CommandConfirmGoldFaction:資金INPUT + 勢力SELECT + OK/Cancel
  • Panel_CommandConfirmOfficer:他勢力武将SELECT + OK/Cancel
  • Panel_CommandConfirmMarch:経路SELECT + 兵数INPUT + OK/Cancel
  • Panel_CommandConfirmReinforce:迎撃/援軍SELECT済 + 兵数INPUT + OK/Cancel

7種すべてをSlidePanelBase継承でモック実装し、Show(コールバック)とHide()のみ実装した。本実装は後回しとした。

ManagerMain対応

7つの確認パネルのSerializeFieldを追加し、InitializeUI()でまとめて初期化する仕組みを入れた。確認パネルの表示・非表示を一元管理するOpenConfirmPanel()/CloseConfirmPanel()を追加し、ViewCommandConfirm状態から右クリック短押しでConfirmパネルを閉じてViewCommandInterface状態へ戻る導線も整えた。

コマンド挙動仕様の確定

通常コマンド・解雇・褒賞それぞれのOK/Cancel時の挙動を確定した。特に褒賞は「OKで忠誠度を即変更(資金10消費・入力なし)、パネルは閉じずそのまま」「コマンド入力済でも褒賞未実行なら実行可能」という特殊仕様を明文化した。Done済カードをクリックしたときはShowReadOnly()で閲覧専用表示を出す方針とした。

BGM方針の変更とACE-Step環境構築

BGM素材を外部配布素材から、ACE-Step V1.5によるオリジナル生成へ切り替えることにした。ローカル環境(v15-turbo / RTX3090)を構築し、生成フローの習得を始めている。自前生成にすることで、ゲームの世界観に合った曲を狙って作れるようにするのが目的である。


■ 27日目(5/25):Panel_CommandInterface本実装・SaveData保存フロー

※5/20〜5/24はACE-Step作業にてゲーム制作はお休み。

コマンド名解決の集約

OfficerCommandCardとPanel_CommandInterfaceに重複していたコマンド名取得処理を、GameEnumExtensions.csのCommandType.GetName()拡張メソッドへ集約した。各ファイルの個別実装を削除し、呼び出しを統一した。

Panel_CommandConfirm本実装

確認パネルのメッセージ領域をメイン・サブの2本構成に変更し、Awake()でのボタン接続を実装した。確認メッセージの定義(各コマンド/解雇/褒賞)もGameEnumExtensions.csに追加し、言語分岐はすべてSystemLanguage enumで処理している。

Panel_CommandInterface本実装

コマンド入力パネルを本実装した。武将データとOfficerSaveDataの解決、ボタン群の表示、君主判定による解雇・褒賞ボタンの制御、コマンド種別ごとの確認パネル振り分け、サブパネル開閉時のinteractable制御までを通した。

コマンド確定→セーブデータ保存フロー

コマンド確定時にOfficerCommandSaveDataを生成し、GameSaveSlot.PlayerCommandsへ追加する流れを実装した。パネルを開き直したときはPlayerCommandsからコマンド一覧を復元して表示する設計とした。これによりターン途中での中断セーブに対応できる。

解雇・褒賞の即時処理

解雇は配下リストから武将を外して在野(WanderingOfficers)へ戻す処理を実装した。褒賞は資金10を消費して忠誠度を上昇させ、HasReceivedRewardThisTurnフラグで「1ターンに同じ武将へは1度まで」の制限をかけた。褒賞の忠誠度上昇量は「((君主の魅力÷10)+10)×乱数0.9〜1.1」で算出する。

反省点

この日は修正→デグレード→修正のループが多発した。既存コードを十分に確認せず修正を出したことが主因で、細切れの修正が積み重なってどこまで適用済みか把握しづらくなった。次回以降は「修正前に影響範囲を明示し、GOが出てからコードを出す」運用を徹底することにした。


■ 28日目(5/26):Panel_CommandInterface残バグ修正

前日の反省を踏まえ、まずは残っていたバグを慎重に潰した。

行動済み(コマンド入力済み)の武将をクリックして開く閲覧専用パネルで、コマンドボタンが全部消えてしまう不具合を修正した。原因はボタン群そのものを非表示にしていたことで、「ボタンは表示したまま、操作だけ無効化する」方式へ変更した。例外として褒賞ボタンだけは、その武将がまだ褒賞を受けていなければ有効化する。

あわせて、褒賞は「行動済みにならない」コマンド(設計書準拠)であるため、閲覧専用表示中でも褒賞だけは実行できるよう制御を見直した。設計書の最新版と突き合わせ、褒賞が行動を消費しない仕様であることも再確認している。


■ 29日目(5/27):情報表示拡充・状態レベル改訂・数値変動演出

この日は分量が多い。順に記録する。

Panel_CommandInterfaceの情報表示拡充

コマンドを入力する際、実行する武将の能力や現在の勢力状況が一目で分かるよう、情報表示を追加した。

武将情報の表示は、既存の共用部品OfficerSimpleInfoを流用する形に一本化した。当初はパネルに直接フィールドを置いて実装していたが、同じものを2か所で持つ無駄を避けるため、また将来の結果表示フェーズで再利用するために、OfficerSimpleInfoへ委譲する方針へ切り替えた。OfficerSimpleInfoのメソッドの引数は変えなかったため、同じ部品を使っている外交向けの武将一覧パネルには一切影響が出ていない。

勢力情報は最終的に8項目を表示することにした。国力・資金・兵数・訓練度・民忠・諜報力に加え、名声と拠点数を追加した。名声は出陣可能な兵数の判断材料に、拠点数は配下枠の解放(あと1拠点で枠が増える、など)の判断材料になるため、見えていて損のない情報と判断した。

状態レベル設計の改訂

これまでシステムボタン群(オプション/ゲーム終了/地図切替/タイトルへ戻る/ズーム)は、コマンド入力状態(レベル1)でのみ表示・操作可能としていた。今回これを見直し、Idle状態(レベル0)で操作できるよう変更した。

新しい構成では、Idleではシステムボタンが画面右からスライドインして操作可能、各種パネルを開いている間(レベル1)はスライドアウトして無効になる。これにより「パネルを開いたままオプションを開く」経路がなくなり、状態管理がすっきりした。地図切替とズームだけは状態を変えずIdleのまま実行できるようにしている。あわせて、無操作10秒で自動的にコマンドパネルが開く挙動は廃止した。

もともと過去にマウス操作のバッティングを避けるためIdleの操作を絞っていた経緯があったが、システムボタンを透明パネル上にまとめて右へ寄せる構成にしたことで、競合なく実現できた。

多言語化の不具合対応

オプションで言語を切り替えたとき、表示中のパネルや地図上の拠点名が即座に切り替わらない問題に対処した。

原因は、武将名や拠点名のように動的に流し込んでいるテキストが、言語変更時の一括更新の対象外になっていたことである(静的に設定したボタン名などは正しく切り替わっていた)。

パネル側は、前述の状態レベル改訂によって「オプションを開けるのはIdleのときだけ=オプション表示中に他のパネルは開いていない」状態が保証されるようになったため、複雑な再描画の仕組みを入れずに済んだ。問題そのものを設計で消した形である。

地図の拠点名については、オプションパネルを閉じたタイミングで全拠点の名前を現在の言語で再解決する処理を入れた。これでOK・キャンセルのどちらで閉じても、拠点名が正しい言語で表示される。

数値変動演出システムの新規導入

数値が「すっ」と変わるだけでは変化が分かりにくいため、汎用の数値変動演出コンポーネント(ChangeValueText)を新規に作成した。

このコンポーネントは、数値のカウントアップ/カウントダウン(1→2→3…と数字が動く)、上昇なら「↑」下降なら「↓」と変動量を示すポップ表示(移動しながらフェード)、そしてアイコンと数値の色分け(上昇=緑/下降=赤)を行う。重要な設計として、演出中に表示される途中の数値はあくまで見た目だけのもので、ゲームデータには一切書き戻さない。データの確定と演出を明確に切り分けている。

まずは褒賞で変動する忠誠度と資金に適用した。褒賞を実行すると、データを確定させたうえで効果音を鳴らし、忠誠度と資金がアニメーションしながら変化する。

効果音キーの定数化とコマンドボタンのデザイン

効果音のキーをシーンごとの定数クラス(SEKeysMain)にまとめ、文字列の直書きをやめてタイプミスを防ぐ構成にした。BGM用の定数クラス(BGMKeysMain)も器だけ用意した(拠点数によるBGM切り替えは仕様確定済み・実装はこれから)。

コマンドボタンのデザインも、Unityデフォルトの仮デザインから、羊皮紙に金枠を添えたゲームの世界観に合うものへ差し替えた。ボタン画像はChatGPTで背景透過・ラベルなしで生成し(ラベルは多言語対応のため別管理)、通常・ホバー・押下・無効の状態差は色味の調整で表現している。

バグ修正

状態レベル改訂に伴い、特定の状況でシステムボタンのスライド処理がエラーを出すようになったため修正した。非表示状態のパネルに対して閉じる処理を呼んでいたのが原因で、不要になっていた1行を削除して解消した。


■ 30日目(5/28):動作確認・進捗整理

29日目までに実装した内容の動作確認を行った。数値変動演出の矢印アイコンの色分け、システムボタンのスライド処理のエラー修正、いずれも問題なく動作することを確認した。あわせてタスク全体の棚卸しを行った。

以下、開発中の画面。少しづつですが、着実に実装を進めています。


■ 現時点の開発状況

カテゴリ状況
データクラス全般✅ 完了
GameUtility✅ 完了
Scene_Initialize✅ 完了
Scene_Title✅ 完成
Scene_Start✅ 完了
Scene_Main(地図表示・スクロール・ズーム)✅ 完了
Scene_Main(勢力情報パネル)✅ 完了
Scene_Main(武将コマンドパネル)✅ 完了
Scene_Main(コマンド設計)✅ 確定
Scene_Main(コマンド確認パネル群)✅ 実装
Scene_Main(Panel_CommandInterface)✅ 完了
Scene_Main(数値変動演出)✅ 完了
Scene_Main(状態レベル設計改訂)✅ 完了
Scene_Main(フェーズ管理・コマンド入力)⬜ 未実装
Scene_Main(戦闘計算・AI)⬜ 未実装
Scene_End⬜ 未着手
コレクション画面・武将登録画面⬜ 未着手

■ 次回の作業予定

いよいよフェーズ管理の本実装に入る。1ターンを7フェーズで構成する設計はすでに確定しており、今回その前段としてコマンド入力まわり・情報表示・状態管理を固めたので、ようやく腰を据えて取り組める段階になった。

メインシーンの状態管理(レベル状態)と、1ターン内のフェーズ進行は別の概念であるため、まずはその整理から着手する予定である。あわせて、褒賞のターン1回制限フラグをターン終了時にリセットする処理も、フェーズ管理の中で対応していく。

【開発[#2] 23日目】戦略SLG

■ 20〜23日目のまとめ

今回は4日分をまとめて記録する。
※5/13、5/16、5/17は私用にて作業お休み。

20日目はScene_Mainの操作設計確定とUI骨格整備、21〜22日目は勢力情報パネルの本実装とデータ構造の大幅整備、23日目はコマンド設計の全体確定と外交情報パネルの本実装、各種バグ修正を実施した。

メインシーンの「見る」部分がほぼ出揃い、次はいよいよ「動かす」フェーズ管理の本実装に入る段階に来ている。


■ 20日目(5/12):操作設計確定・Panel_System新規作成

コマンド入力フェーズの操作設計確定

メインシーンの状態遷移と操作制御を確定した。

Idle状態では右ドラッグでマップスクロール、マウスホイールでズーム、拠点アイコンまたは勢力地図パーツの左クリックで地図情報パネル表示状態(ViewInfo)へ遷移する。それ以外への左クリック、または無操作10秒でUIパネル表示状態(CommandInput)へ自動遷移する。

右クリックは「短押し(0.2秒以内・離し時発火)」を遷移トリガーとし、右ドラッグと明示的に分離した。ViewInfo状態ではマップ操作を禁止し、情報閲覧に専念する設計とした。

Panel_System新規作成

セーブ・オプション・タイトルバック・ズームなどのシステムボタン群をManagerMainから独立させ、Panel_System.csとして切り出した。コールバック(Action)方式でManagerMainと連携する構成で、今後の状態制御が一元化しやすくなった。

ManagerMain改修

右クリック短押し判定を実装し、_rightDraggingフラグで押し時間を計測して離し時に発火する方式とした。MapContainer自体にButtonを設置するSetupMapClickHandler()を新設し、拠点・地図パーツ以外への左クリックをフォールバック処理する仕組みにした。これにより左クリックの吸い取り問題が解消した。

またBGM設計も確定した。プレイヤー保有拠点数に応じて5段階でBGMを切り替える方式で、使用素材はperitune.com(無料・商用利用可・ゲーム同梱可)を予定している。


■ 21〜22日目(5/14〜5/15):勢力情報パネル本実装・OfficerSaveData導入

Panel_FactionDetailInfo本実装

地図上の拠点または勢力地図パーツをクリックしたときに表示される勢力情報パネルを本実装した。表示項目は勢力名・勢力カラー・君主情報(顔小画像・名前)・各種ステータス(資金・兵数・国力・訓練度・民忠誠度・諜報力・名声・拠点数)・友好度・信頼度。

諜報レベルによる情報フィルタリングをGameUtility.GetIntelligenceLevel()として実装した。レベルに応じて閲覧できる情報が段階的に開放される。

  • レベル0:勢力名・拠点数のみ
  • レベル1:国力・君主情報(顔・名前)
  • レベル2:資金・兵数・民忠・名声
  • レベル3:全情報(訓練度・諜報力・外交情報)

プレイヤー自身の勢力はフィルタリングなし(レベル3扱い)。数値・記号専用のテキストはLocalizeTextを使用せずTextMeshProUGUI直接参照とする方針を今回から徹底している。

OfficerSaveData新設・全ファイル対応

武将データの管理構造を大幅に整理した。従来のSubordinateIds/CustomSubordinateIds(IDリスト2本)を廃止し、OfficerSaveDataクラスに統合した。MonarchId/CustomMonarchIdも廃止してOfficerSaveData Monarchに一本化した。

フィールド構成はOfficerId / CustomId / CurrentLoyalty / IsNormalの4つで、通常武将とカスタム武将を同一クラスで扱える。武将の解決はGameUtility.ResolveOfficer()経由で行う運用を徹底する。

対応ファイルはSaveDataGame.cs / GameUtility.cs / Panel_FactionDetailInfo.cs / ManagerStart.cs / DebugSaveDataCreator.csの5ファイル。構造変更に合わせてgame.jsonも再生成し、動作確認まで完了した。

Panel_FactionDetailInfoOfficer本実装

サブパネルとして武将一覧を表示するPanel_FactionDetailInfoOfficer.csを本実装した。表示枠は10枠固定(君主1名+配下最大9名)。

1枠を担当するOfficerSimpleInfo.csを新規作成した。表示項目は顔小画像・兵科アイコン・武将名・忠誠度・特技・武力/知力/魅力。君主の忠誠度は常に「—」で固定。配下の忠誠度は諜報レベル3以上またはプレイヤー勢力の場合に数値表示、それ以外は「???」でマスクする。


■ 23日目(5/18):コマンド設計確定・外交情報パネル本実装・バグ修正

コマンド設計確定

CommandType enumをGameEnums.csに追加し、全コマンド体系を確定した。

  • 内政系:開発 / 施し / 徴発
  • 軍事系:出陣 / 徴兵 / 募兵 / 訓練 / 迎撃
  • 外交系:同盟 / 親睦 / 要請 / 破棄
  • 人事系:捜索
  • 謀略系:諜報 / 計略 / 引抜
  • 援軍系:援軍出陣 / 援軍迎撃

解雇・褒賞はコマンドクラス管理外で即時処理、迎撃・援軍はWarクラスで別途管理する設計とした。要請コマンドは同盟勢力全員へ自動送信(個別指定不要)。出陣は経路指定方式(OriginBastionId+TargetBastionId)で戦争の一意特定を行う。

ランタイム用のOfficerCommand.csを新規作成し、セーブ用のOfficerCommandSaveDataをSaveDataGame.csに追加した。GameSaveSlot.PlayerCommandsでターン中断セーブに対応、GameSaveSlot.UnlockedSubordinateSlotsで開放済み配下枠数を永続管理する。

Panel_FactionDetailInfoDiplomacy本実装

外交情報サブパネルを本実装した。表示枠は9枠固定で敗北済み勢力を除外して表示する。

1枠を担当するDiplomacySimpleInfo.csを新規作成した。表示項目は勢力名・同盟有無・友好度(数値+段階テキスト)・信頼度(数値+段階テキスト)。このパネルは外交ボタン自体が諜報レベル3でのみ開放される前提のため、表示はレベル3固定とした。

信頼度の段階テキストを今回確定した。友好度とは別定義で以下の通り。

数値日本語英語
0〜19敵視Hostile
20〜39不信Suspicious
40〜59中立Neutral
60〜79好意Trusting
80〜99信頼Devoted
100信任Absolute

多言語対応改善

マスクテキストを言語依存のGetMaskText()メソッドに変更した。日本語は「???」、英語以降は半角「???」を返す。数値テキスト向けのマスクはMaskTextNumeric定数(半角「???」固定)に統一した。

Panel_Commands・Panel_CommandInterface実装

旧Panel_OfficerCommandCard.csをOfficerCommandCard.csに置き換えた。CardStateはEmpty / Locked / Idle / Doneの4種で、空席・ロック状態は顔画像欄に専用画像を表示する方式とした。

Panel_CommandInterface.csをモック実装した。ShowInput()(コマンド入力モード)とShowReadOnly()(閲覧専用モード)を実装し、onCloseコールバックに対応した。

バグ修正

今回は4件のバグを修正した。

  • ロードゲーム→タイトル→新規ゲームでロードデータが残留する問題:ManagerMain.Start()でNewGameData.Clear()が呼ばれていなかったのが原因。ロード・新規どちらのルートでも呼ぶよう修正した。
  • Panel_CommandInterface初期表示バグ:InitializeUI()でHideImmediate()の呼び出しが重複・漏れていたのが原因。
  • ViewCommandInterface状態から右クリックで戻れないバグ:Update冒頭のisViewCommandInterface変数が未定義だったのが原因。
  • Panel_CommandInterface閉じるボタンで状態遷移しないバグ:onCloseコールバック未実装・_onCardClick誤呼び出しが原因。Panel_Commands側にonCommandInterfaceCloseコールバックを追加し、ManagerMain側でViewCommands状態への遷移を統一した。

■ 現時点の開発状況

カテゴリ状況
データクラス全般✅ 完了
GameUtility✅ 完了
Scene_Initialize✅ 完了
Scene_Title✅ 完成
Scene_Start✅ 完了
Scene_Main(地図表示・スクロール・ズーム)✅ 完了
Scene_Main(勢力情報パネル)✅ 完了
Scene_Main(武将コマンドパネル)✅ 完了
Scene_Main(コマンド設計)✅ 確定
Scene_Main(フェーズ管理・コマンド入力)⬜ 未実装
Scene_Main(戦闘計算・AI)⬜ 未実装
Scene_End⬜ 未着手

■ 次回の作業予定

フェーズ管理の本実装に入る。1ターンを7フェーズで構成する設計はすでに確定しており、コマンド入力フェーズと結果表示フェーズの流れを繋ぐところから着手する予定。

【開発[#2] 19日目】戦略SLG

■ 18〜19日目のまとめ

今回は2日分をまとめて記録する。

18日目はScene_StartからScene_Mainへのデータ受け渡し経路を確立し、メインシーンの骨格を実装した。19日目はマップの大幅強化と武将コマンドパネルの骨格実装を中心に進めた。
メインシーン制作へ本格的に着手し始めたが、設計書作成などあまり画像を出せないフェーズでの作業が多く、今は進捗立証が難しい段階です。


■ 18日目(5/10):データ受け渡し経路の確立とScene_Main骨格

データ構造の整備

GameEnums.csにGameResult.InProgress(値:-1)を追加し、従来のIsInProgress boolフラグを廃止して一本化した。あわせてカスタム武将の君主・在野登録対応としてFactionSaveDataにCustomMonarchId、WanderingOfficerSaveDataにCustomIdを追加した。

GameStartData新規作成

Scene_StartからScene_Mainへの初期データ受け渡し専用のstatic classを作成した。

ScenarioDataのマスタは一切書き換えず、全データを複製してGameSaveSlotとして渡す設計にした。NewGameDataとは独立した受け渡し口として機能する。Scene_MainのStart()で参照後にClear()を呼ぶことで使い捨てにする。

OnClickStart()本実装

以下の処理を実装した。

BuildInitialSlot()でScenarioDataを全複製し、プレイヤーの編集内容(君主・配下・勢力名)を上書き。BuildWanderingOfficers()で全武将を走査して在野登録。ResolveDisplacedFactions()でプレイヤーが他勢力から引き抜いた武将の代替を各勢力に割り当て。

引き抜きが発生した場合の処理も実装した。他勢力の君主を引き抜いた場合は配下の中から能力値合計最大の武将を格上げし、空いた枠には同レアリティの在野武将をランダム補充する。在野武将が同レアリティで見つからない場合は一段下で再抽選し、それでもなければ打ち切りとした。

Scene_Main骨格実装

GameSaveSlotからデータを受け取り地図表示を実装した。NewGame時はGameStartData.Slot、LoadGame時はManagerSaveData.GameData.Slots[index]を参照する。ScenarioDataはマスタ参照のみ(読み取り専用)。

地図は拠点図・勢力図の切替に対応した。ターン送りボタン、タイトルバック・ゲーム終了ボタンも実装した。フェーズ管理・コマンド・戦闘・AIは引き続き未実装。


■ 19日目(5/11):マップ強化・コマンドパネル・情報引き渡し対応

ボタン登録方式の統一

ManagerMain・ManagerStart・ManagerTitleの全ボタンについて、Inspector直設定からAddListener方式に統一した。

従来は一部ボタンがInspector上のOnClickリストに直接設定されており、状態遷移による一括制御ができない問題があった。RegisterButtons()を新設してStart()から呼ぶ方式に統一し、全ボタンで状態チェック(_state != Idle)が機能するようにした。コードを見れば全ボタンの挙動が把握できる状態にすることが目的で、InspectorとコードのどちらかだけでなくどちらもあわせてOnClickを確認しなければならない状態を解消した。

ワールドマップの2倍化

1920×1080のワールドマップをそのまま使用するとエリア戦で未使用エリアが広く残り見栄えが悪いため、3840×2160に拡大する方針に変更した。

単純な拡大ではピクセルが荒れるためAIアップスケーリングを採用した。Real-ESRGANのアニメ・イラスト向けモデル(RealESRGAN_x4plus_anime)をローカル環境で実行し、ディテールを保ったまま2倍化した。RTX3090 + CUDA環境で短時間で処理できた。Pythonとpipで環境を整えるだけで動作し、登録や料金は不要。

MapContainerの導入とスクロール・ズーム実装

Canvas_Main直下に3840×2160のMapContainerを新設し、Layer_Territory・Layer_Connection・Layer_Bastionを配下に移動した。

スクロール

右クリックまたは中ボタンドラッグで地図をスクロールできる。マップ外にはみ出さないようClampMapPosition()でスクロール範囲を制限している。

ゲーム開始時はプレイヤー勢力の所有拠点の重心座標を自動計算し、その位置が画面中央に来るよう初期表示位置を調整する。

ズーム

100%・75%・50%の3段階ズームに対応した。マウスホイールとズームボタン(3つ)の両方で操作できる。ズーム中心はマウスカーソル位置基準で計算している。拠点アイコンと接続ラインはRebuildPositions()でズーム倍率に追従して再配置する。ズーム時はSmoothStep補間による0.15秒のアニメーションを挟む。

GameUtility.cs新規作成

通常武将(OfficerDatabase)とカスタム武将(RecordData)からIOfficerを解決する共通ユーティリティとしてGameUtility.csを新規作成した。

Scene_Startでは用途が限定的だったため該当箇所に直書きしていたが、Scene_Mainではコマンド処理・AI処理・戦闘処理など至る所でIOfficer解決が必要になるため共通化した。今後はこのユーティリティを経由することを徹底する。

武将コマンドパネル骨格実装

メインシーン下部に武将カードを最大10枚並べるPanel_Commandsを実装した。左クリックで下からスライドイン、右クリックでIdle状態へ戻る。Panel_OfficerCommandCardが1枚のカードを担当し、顔画像(256×256・FaceSmall)と武将名を表示する。

これに合わせて256×256の切り出しスプライト(FaceSmall)を新規追加した。OfficerSpriteImporterで既存の_Faceスプライト(384×384)に加えて_FaceSmall(上部中央256×256)を一括登録できるよう拡張した。カスタム武将もImageImporter.CropFaceSmall()で生成・保存するよう対応した。

ManagerMainの状態遷移にCommandInput(コマンドパネル表示中)を追加した。

以下は、まだモックアップ実装の段階だが、マップの拡大/縮小とスクロールに対応したメイン画面。

勢力名・君主名のJp/En分離対応

従来、勢力名と君主名は1つの入力フィールドで日英共用していた。フォントアセットの言語対応の観点から、日本語・英語を独立した入力フィールドに分離した。未入力のままにすればデフォルト値がそのまま使われる。

Panel_FactionEditの入力フィールドをJp/En各2つに拡張し、Panel_FactionConfirm・ManagerStartも対応した。FactionSaveDataにMonarchNameJp・MonarchNameEnを追加してScene_Mainへの引き渡しに対応した。

また君主顔画像の差し替え情報(FaceSmallPathを含む)もGameSaveSlot経由でScene_Mainに引き渡すよう対応した。武将コマンドカードでは君主カードのみ、編集済み名前とFaceSmall画像をOverrideName/OverrideFace()で上書き表示する。

ゲーム設計書の整備(Googleドキュメント)

実装と並行してゲーム設計書をGoogleドキュメントで整備した。

今回確定・追記した内容は以下の通り。

ゲームフェーズ設計 1ターンを7フェーズで構成することを確定した。ユーザー入力が発生するのは④結果表示フェーズと⑥コマンド入力フェーズのみで、それ以外はクリックによるページ送り待ち程度に抑える設計としている。

コマンド仕様 内政・軍事・外交・人事・謀略の全コマンドについて計算式・適用特技・例外処理を確定した。武将1名につき1コマンドを入力する方式で、拠点数に応じて配下枠が最大9名まで拡張する仕様も確定している。

戦闘仕様 ベース戦力値の計算式、兵科補正テーブル、三つ巴以上の戦争処理、兵力の決算式、捕縛確率まで一通り確定した。

AI行動仕様 行動優先度を8段階で定義した。1年目は戦争しない・計略引抜は実行しないなどの制約ルール、同盟検討ロジック、難易度ボーナスの方針も記載した。

シーン内UI構成 状態遷移の定義を追記した。現時点では骨格のみで画面レイアウトは次フェーズで確定予定。

設計書は実装の進行に合わせて随時更新していく運用としている。


■ 現時点の開発状況

カテゴリ状況
データクラス全般✅ 完了
GameUtility✅ 新規完了
Scene_Initialize✅ 完了
Scene_Title✅ 完成
Scene_Start✅ 完了
Scene_Main(地図表示)✅ 完了
Scene_Main(スクロール・ズーム)✅ 完了
Scene_Main(武将コマンドパネル骨格)✅ 完了
Scene_Main(フェーズ管理・コマンド)⬜ 未実装
Scene_Main(戦闘計算・AI)⬜ 未実装
Scene_End⬜ 未着手

■ 次回の作業予定

シーン内UI構成の設計を固めてから、コマンドメニューの実装に入る。フェーズ管理の骨格を先に作り、コマンド入力→結果表示の流れを繋ぐ予定。

【開発[#2] 17日目】戦略SLG

■ 12〜17日目のまとめ

今回は6日分をまとめて記録する。

前回まででScene_Titleの基本実装は終わっていたが、各画面のデザインが仮素材のままだった。今回はそこを仕上げ、タイトルシーンを一旦完成とした。あわせてScene_Startの機能実装を本格的に進め、君主選択制御・武将変更パネルまで動くようになった。

結構、Claudeの提案に振り回される展開も多く、手戻りに近い無駄な工程もあったのでAIをディレクションする能力を高めるべきと反省する局面が多かった。前提条件にいつの間にか認識齟齬があったり、複雑化するほど丁寧な要件指定が必要と痛感した。
小さく閉じた機能設計精度は高いが規模が大きくなって複雑化してくると業務系アプリケーションではあまり問題ないのかもしれないが、ゲームのような独自性が高いアプリケーションだとAIの推論が的外れになる事も多いですね。


■ 12日目(5/3):バグ修正・多言語化対応・各種画面実装

LocalizeHelperの削除と多言語化設計の統一

大規模な対応となった。それまで使っていたLocalizeHelper.cs(日本語・英語の2言語決め打ちでテキストを返すユーティリティ)を全廃した。

理由は拡張性。bool isJapaneseの二択設計では将来的に中国語やドイツ語を追加できない。代わりにSystemLanguage型のswitch式を使う方針に統一した。この変更が影響したファイルは14本・34箇所にのぼった。

LocalizeText.SetDynamicText()への統一も同時に行い、TextMeshProUGUIには必ずLocalizeTextをアタッチするプロジェクト標準を確立した。

コレクション画面(Panel_Collection)実装

タイトルシーンの武将図鑑画面を実装した。

全132名をID順にNo.1〜No.132で表示する。24名/ページ(横8×縦3)・最大6ページのページング構成。CollectionCard.csをPrefab化してCommonフォルダに配置し、登録済み/未登録(?????表示)の2状態を持つ設計にした。

カードをクリックするとPanel_OfficerDetailが開き、立ち絵・能力値・兵科・特技・経歴などの詳細を確認できる。

カスタム武将登録画面(Panel_ForgeOfficer / Panel_CustomOfficerEdit)実装

「My Officers」から起動するカスタム武将登録機能を実装した。

画像を取り込むとSHA256ハッシュ値を生成し、そのハッシュをシードとしてパラメータを自動生成する。同じ画像からは必ず同じ結果が得られる設計になっている。

自動生成の内容:

項目方式
能力値(武力/知力/魅力)正規分布(Box-Muller法・平均60・標準偏差15)
初期忠誠均等分布(60〜90)
ボーナスポイント均等分布(10〜30)
兵科重み付き抽選(均等5種)
特技シード固定抽選(42種)

特技に兵科縛りがある6種(騎馬突撃・弓の名手・槍衾・剣聖・魔法集中・魔法陣)については、特技抽選後にUnitTypeを強制上書きする処理を入れている。

ボーナスポイントは各能力値に±ボタンで振り分けられる。元の生成値より下には下げられない制約あり。

確定後は変更不可・削除のみ可能という設計で確定した。

LoadGame画面実装

タイトルシーンのデータ読込画面を実装した。

オートセーブ1枠+手動3枠の計4スロット構成。各スロットにはシナリオ名・難易度・現在ターン(年・季節換算)・勢力名を表示する。エリア戦(青)・全土戦(赤)で背景色を色分けし、データなしスロットはグレーで読込ボタンを無効化する。

ターン数の変換は以下の通り。

エリア戦:最大40ターン(10年)
全土戦:最大80ターン(20年)
上限超過:「期限切れ」表示

■ 13日目(5/4):SlidePanelBase実装・パネル演出の共通化

SlidePanelBase

各パネルのスライドイン・スライドアウト演出を提供する共通基底クラスを作成した。

スライド方向(上下左右)・時間・距離はInspectorで設定可能。オプションでCanvasGroupによるフェードイン・アウトにも対応している。公開APIはShow() / Hide() / ShowImmediate() / HideImmediate() / SetInteractable()の5種。

この回から全パネルが継承対象となり、現時点では以下が対応済み。

Panel_Scenario / Panel_Difficulty / Panel_LoadGame / Panel_Collection / Panel_OfficerDetail / Panel_ForgeOfficer / Panel_CustomOfficerEdit / Panel_ImageImport / Panel_Option / Panel_Dialog / Panel_FactionInfo / Panel_FactionConfirm / Panel_FactionEdit / Panel_OfficerSelect

Panel_OptionとPanel_Dialogの配置方針変更

旧方針のDontDestroyOnLoad・Singletonパターンを廃止した。各シーンに直接Prefabを配置し、SerializeFieldで直接参照する方式に変更した。

ManagerOption・ManagerDialogという名称もPanel_Option・Panel_Dialogにリネームし、命名規則(Panel_*プレフィックス)に統一した。


■ 14日目(5/6):カスタム武将画面の修正・操作制御整備

ScrollView修正とCanvasGroup操作制御

カスタム武将一覧のScrollViewで、カードがContent配下ではなくScrollView直下に追加されて重なって表示される不具合を修正した。SerializeFieldのアサイン漏れが原因だった。

操作制御の方針をこの回で確定した。パネルが開いている間は他パネルの操作を一切不可とする。親子パネルが重なる場合はCanvasGroupのinteractable制御を使う。SetInteractable()をSlidePanelBaseの公開メソッドとして追加した。

最終更新日時機能

CustomOfficerDataにLastModifiedAtフィールドを追加した。ISO 8601形式で保持し、表示時は言語に応じたフォーマットで出力する。

日本語:yyyy/MM/dd HH:mm
英語:MMM dd, yyyy HH:mm

■ 15日目(5/7):CollectionCard・CustomOfficerEdit改修

CollectionCard改修

未登録カードの飾り枠が実行時に消える不具合を修正した。Sprite Frame Secretが未アサインのままspriteにnullが入っていたのが原因だった。

未登録用素材を分離した。変更前は顔・兵科共通の_spriteSecretを1枚使っていたが、_spriteSecretFace(顔用)と_spriteSecretUnitIcon(兵科用)に分離した。

ステータス表示(武力/知力/魅力)も追加した。登録済みは実数値、未登録は「??」表示。兵科アイコンカラーは#C8A84B(ゴールド)で統一した。

Panel_CustomOfficerEdit改修

兵科アイコン画像表示と特技説明文表示を追加した。特技説明文はGameEnumExtensions.GetDescription()で取得し、ClearParamDisplay / ApplyGeneratedData / LoadEditTargetの各タイミングで更新する。

GameEnumExtensionsにUnitType重み付き抽選メソッドGetWeightedUnitType(int seed)を追加した。スキル縛りなし時の兵科抽選に使用する。


■ 16〜17日目(5/8〜5/9):タイトルUI完成・スタートシーン本格実装

タイトルシーン3画面のデザイン確定

この段階でタイトルシーンを一旦完成とした。

ロード画面はセーブスロットの背景を色設定からSprite差し替え方式に変更した。エリア戦(青系)・全土戦(赤系)・データなし(グレー系)で別素材を使う。パネル上部に「Select Save Data」タイトルラベルを追加した。

シナリオ選択画面はエリア戦ボタンを青・全土戦ボタンを赤の別Spriteで色分けした。文字のシャドウはTMPのマテリアル制約をShadow用テキストオブジェクトの並置で回避した。

難易度選択画面はEasy(緑)・Normal(青)・Hard(赤)の横並びアイコンボタンに変更した。

ツールチップ実装

ホバーでテキストを表示するTooltipUI.cs・TooltipTrigger.csを新規作成した。

言語テキストはSystemLanguageエントリ方式で管理しており、言語追加時はInspectorにエントリを追加するだけで対応できる。CanvasGroupのinteractable=false時は表示しない制御を入れており、操作無効状態でのホバーにも対応している。

拠点データ拡充

エリア戦の拠点数が少なすぎると感じたため、各エリアに追加した。

エリア全国版拠点エリア専用追加合計
Area1(北部山地)104(B111〜B114)14
Area2(東海地方)84(B209〜B212)12
Area3(南部平野)125(B313〜B317)17

全拠点IDの管理を2桁(B)から3桁(B*)に統一した。BastionDataImporter.csのフォーマット指定をD2→D3に修正し、既存アセットもUnityエディタ上でリネームした。

接続設計はPythonスクリプトで地図上に可視化して確認した。一方通行チェックも全エリア・全土戦で実施済み。

勢力データ拡充

拠点増加に合わせて各シナリオの勢力数を増やした。

シナリオ追加勢力
S01アイゼンガルド辺境伯領 / ヴァルドレン王国
S02ティレニア海洋同盟 / コーラル諸島連邦
S03ヴェルディア王国 / サンフィールド伯爵領 / テラヴェルデ共和国

各勢力の識別カラーは既存15勢力と被らないよう選定した。

武将12名追加

コレクション画面が6ページきっちり埋まるよう武将を12名追加した。CSVインポートとシナリオ反映を確認済み。

スタートシーン:パネルのSlidePanelBase移行

Panel_FactionInfo・Panel_FactionConfirm・Panel_FactionEditをSlidePanelBase継承クラスに変換した。

SlidePanelBaseにSetSlideDirection()を追加し、パネルの左右スライド方向を動的に変更できるようにした。ただし今回のPanel_FactionInfoは固定方向(右)に統一し、コードからの動的制御をやめてInspector設定に一本化した。

ManagerStart.InitializeUI()でgameObject.SetActive(true)後にHideImmediate()を呼ぶ方式をManagerTitleから踏襲した。Hierarchyのアクティブ・非アクティブ状態に動作が左右されないよう徹底している。

Overlayによる操作ブロック方式を廃止し、CanvasGroupのSetInteractable()に完全移行した。StartSceneStateにFactionEdit状態を追加して全状態での制御を一元化した。

君主選択制御

スタートシーンの主要機能となる君主選択の可否制御を実装した。

条件選択可能な君主
全土戦unlockedOfficerIdsに登録されている君主
エリア戦・初回全国シナリオに登録されている君主
エリア戦・クリア後そのエリアシナリオの全君主

選択不可の勢力は城アイコンを暗色で表示し、地図上から視覚的に判別できるようにした。Panel_FactionConfirmでは選択不可時にStart等のボタンをinteractable=falseにし、理由を示すメッセージを表示する。全土戦とエリア戦でメッセージ内容を出し分けている。

勢力データはScenarioDataのマスタを直接書き換えず、ManagerStart起動時にFactionScenarioData.Clone()で複製したものを使う設計にした。

Panel_OfficerSelect 新規実装

全土戦の君主・配下変更用武将選択パネルを実装した。

CollectionCardを横8枚・縦スクロールで一覧表示する。コレクション武将→カスタム武将の順で続けて並べる設計のため切り替えボタンは不要になった。

フィルタ機能として兵科ボタン・能力値スライダー(武力/知力/魅力)・特技ドロップダウンを実装した。特技ドロップダウンはEnumのValueが飛び番(1〜6の後が11〜)になっているため、_skillEnumValuesリストでindex↔Value対応表を持つ方式にした。

カードをクリックすると即確定・パネルを閉じる。

IOfficerインターフェース導入

OfficerDataとCustomOfficerDataの共通化のためIOfficer.csを新規作成した。

GetName() / GetBiography()
Strength / Intelligence / Charisma / DefaultLoyalty
UnitType / SpecialSkill / Personality / Rarity
GetFaceSprite() / GetStandingSprite()
IsCustom

両クラスに明示的インターフェース実装で追加した。フィールドのプロパティ化はScriptableObjectのシリアライズを破壊するため禁止とし、IOfficer.Strength => Strengthの形で実装した。

これによりOfficerCard.Setup()・Panel_OfficerSelect・Panel_FactionConfirmの武将一時変更データをすべてIOfficer型で統一できた。メインシーンでの戦闘計算・AI処理でも型分岐が不要になる見込み。

Panel_FactionConfirmの武将一時変更設計

確定パネル上での武将変更は、開始ボタンを押すまで一時データとして扱う設計にした。

_tempMonarch(IOfficer):君主の一時変更
_tempSubordinates(IOfficer[]):配下の一時変更

Show()時にnullリセット、リセットボタンでnullに戻す。実データ(_factionListのClone)はキャンセルしても書き換わらない。開始ボタン押下時にGetTempMonarch() / GetTempSubordinates()で確定データを取得してGameStartDataを生成する設計になる。

カスタム武将の在野登録フラグ追加

CustomOfficerDataにIsWanderingInNational(bool)フィールドを追加した。

全土戦でカスタム武将を在野武将として登場させるかどうかを制御するフラグ。Panel_CustomOfficerEditにトグルを追加して編集可能にした。

武将選択画面ではこのフラグに関係なく全カスタム武将が選択対象になる。ゲーム開始後、選択されなかったカスタム武将のうちIsWanderingInNational=trueのものが在野武将として登場する。

スーパーゲ制デー(5/9)

毎月第2土曜日のスーパーゲ制デーに合わせてXに開発進捗動画を投稿した。

タグ(#スーパーゲ制デー)は長文投稿の折りたたまれた範囲に入ると検索インデックスに乗らないことを確認した。タグは投稿冒頭に配置するか、別リプライにタグのみ投稿する方式が確実。
Xに関してはフォロワーを増やす為だけの活動はアカウント品質低下を招くと判断し、内容のあるPOSTを心掛けて地道に展開したいと思う。実際、相互しますで増えたフォロワーはPOST内容に興味が無さそうでインプレッション率(POSTのインプレッション数/フォロワー数)の悪化しか招かない結果に(笑)
しかし、POSTに反応が増えてくるとやる気がアップしますね。


■ 現時点の開発状況

カテゴリ状況
データクラス全般✅ 完了
IOfficerインターフェース✅ 新規完了
GameStartData✅ 新規完了(実装は次回)
Scene_Initialize✅ 完了
Scene_Title✅ 一旦完成
Scene_Start(UI・操作制御)✅ 完了
Scene_Start(君主選択制御)✅ 完了
Scene_Start(武将変更パネル)🔶 デザイン調整中
Scene_Start(ゲーム開始処理)🔶 未実装
Scene_Main⬜ 未着手

■ 次回の作業予定

Panel_OfficerSelectのデザイン仕上げ後、Scene_Mainの実装に入る。

GameStartData.CreateFromScenario()の実装・OnClickStart()の本実装から始め、マップ表示・ターン制御・コマンド実装と進める予定。

【開発[#2] 11日目】戦略SLG

■ 10〜11日目のまとめ

今回は2日分をまとめて記録する。

10日目はScene_Startの基本実装が中心。勢力選択から確定まで一通りのUIフローが動くようになった。11日目はそこに機能を追加しつつ、データ設計の抜け漏れを潰した。


■ 10日目:Scene_Start 基本実装

勢力選択・確定フロー

Scene_Startのメインとなる画面遷移を実装した。

世界地図上の拠点アイコンをクリックするとPanel_FactionInfoが表示され、勢力の基本情報を確認できる。そこから「選択」を押すとPanel_FactionConfirmに遷移し、君主・配下武将のカード表示、各種変更ボタンが並ぶ確定ウィンドウになる。

拠点表示モードと勢力図モードの切り替えも実装済み。勢力図モードはalphaHitTestMinimumThresholdで透過部分のクリック判定を除外している。

状態管理

6状態のEnumで一元管理している。

Idle / FactionInfo / FactionConfirm / OfficerSelect / FaceImageSelect / ErrorDialog

状態によって操作可否を切り替える設計で、後の機能追加時にも拡張しやすい構造にした。

OfficerCard Prefab

武将カードUIをPrefab化してCommonに配置した。勢力確定ウィンドウと武将選択ダイアログで共用する。顔絵・名前・兵科・特技・三能力値を表示する。


■ 11日目:機能追加とデータ設計

配下武将変更ボタン

Panel_FactionConfirmの配下武将カード下部にボタンを配置した。

ScrollViewの配下カード列と並列にPanel_SubChangeButtonsを置き、配下数に応じてボタンをInstantiateする方式にした。LayoutGroupの動的生成でいくつか試行錯誤があったが、ラッパー構造は使わず並列配置で解決した。後でデザインボタンに差し替える予定なので、ボタンはPrefab(OfficerChangeButton)から生成する設計にしている。

君主画像差し替え機能

顔変更ボタンから起動する画像取り込みウィンドウを実装した。

Panel_ImageImportはCommon配置のPrefabで、カスタム武将登録でも流用できる設計にしている。OSのファイル選択ダイアログにはStandaloneFileBrowserを使用した。取り込んだ画像は512×768にリサイズし、上部384×384を顔絵として自動切り出しする。

対応フォーマット:PNG / JPG / JPEG
最大ファイルサイズ:10MB
出力サイズ(立ち絵):512×768
出力サイズ(顔絵):384×384(上部中央クロップ)

画像処理はImageImporter.csとして共通化した。

勢力名・君主名の編集機能

Panel_FactionEditを新規作成した。勢力確定ウィンドウの「勢力編集」ボタンから開き、勢力名と君主名をその場で変更できる。

文字数制限は以下で確定した。

項目日本語英語
武将名15文字19文字
勢力名10文字25文字

この制限値は武将登録画面でも共通仕様となる。

SaveDataRecord の新規設計

アプリ通算の実績データクラスを新規に設計・実装した。

これまでセーブデータはSaveDataSystem(設定)とSaveDataGame(プレイ進行)の2種類だったが、コレクション解放状況やカスタム武将管理のためにSaveDataRecordを追加した。SaveDataCustomOfficerとして別管理を検討していたが、ファイルを増やしたくないという方針からSaveDataRecordに統合した。

フィールド内容
areaClearRecordsエリア戦クリア記録(シナリオIDごと)
nationalClearCount全国版クリア回数
unlockedOfficerIdsコレクション解放済み武将IDリスト
customOfficerSlotCountカスタム武将スロット上限
customOfficers登録済みカスタム武将リスト

バージョンマイグレーション機構も組み込んだ。アップデートでフィールドを追加した場合は、ロード時に旧バージョンのデータを自動補完する。

ManagerSaveData の拡張

SaveDataSystem・SaveDataRecordの両方を同じ初期化フローで管理するように整理した。初回起動判定はisInitializedフラグで行い、ファイルパスの参照はManagerSaveData内に集約している。

ユーティリティメソッドも追加した。

IsNationalScenarioUnlocked()  // 全国版解放判定
IsAreaCleared(scenarioId)     // 指定シナリオのクリア判定
CalcCustomOfficerSlotCount()  // スロット上限の算出

Scene_Title:状態管理の刷新

TitleSceneState EnumをManagerTitle.csに導入した。これまでboolを複数管理していたが、Enumに一元化して各ボタンイベントに状態チェックを入れた。状態の階層構造は以下の通り。

Opening → WaitingInput → MainMenu(起点)
                              ├ ScenarioSelect → DifficultySelect → StartScene遷移
                              ├ Collection
                              ├ ForgeOfficer
                              ├ LoadGame
                              └ Option

同一レベル間の平行移動はなし、戻るは常に1レベル上へ、という設計で統一している。

Panel_Scenario.cs 新規作成

シナリオ選択パネルの専用スクリプトを作成した。シナリオ名のテキスト表示(LocalizeText使用)と、全国版ボタンの有効/無効制御を実装している。全国版かどうかの判定はIsNationalScenarioフラグで行い、シナリオIDのマジックナンバーは使用していない。キャンセルボタンも追加した。

今回からパネルごとに専用スクリプト1本という方針を確立した。


■ 現時点の開発状況

カテゴリ状況
データクラス全般✅ 完了
SaveDataRecord✅ 新規完了
Scene_Initialize✅ 完了
Scene_Title(基本)✅ 完了
Scene_Title(Collection・ForgeOfficer・LoadGame)🔶 未実装
Scene_Start(基本UI)✅ 完了
Scene_Start(武将選択・遷移)🔶 未実装
Scene_Main⬜ 未着手

■ 次回の作業予定

タイトルシーンの残実装(Collection・ForgeOfficer・LoadGame)を優先して進める。Scene_Startのスタートボタン遷移はその後。