2016年12月23日金曜日

Bwars 2 ベータ版延期のお知らせ


 Bwars2のベータ版はクリスマスにリリースを目指していましたがプライベートでシリアスな問題が起きたため、延期いたします。来年の1月中にリリースを目指すのでよろしくお願いします。

 I regret to say Bwars2 beta release on this Christmas was postponed due to serious issue just happened in my life. I try my best to release the beta in January 2017.

2016年12月4日日曜日

【Unity】 RTS : Bwars 2 補給システムと中隊


 これまでユニットはAIの思考の都合上数個のユニットでチームを編成していたが、それをゲーム上でも(つまりプレーヤーが操作する場合でも)操作の単位とすることにした。ユニットは小隊、ユニットで構成されるチームは中隊として扱われ、中隊指揮官を割り当てることができるようになった。指揮官は能力により中隊にボーナスを与えることができるので、ここで指揮官同士を差別化することができる。AIとプレーヤーの間の指揮権の移譲も中隊単位となり、ある中隊に属するユニット郡をプレーヤーとAIで分かち合うことは出来ない。つまりプレーヤーが操作をしようとした場合最低でも1個中隊を操作する必要があるが、中隊は4個小隊で構成されるのでRTS初心者でも十分操作可能と考えている。そもそも中隊の導入で操作するユニットの数は減っており、4個中隊の場合は全軍でも16個小隊と少ない。下のの写真は中隊の編成画面を示している。


 中隊の導入に伴い補給も中隊単位とした。各ユニットは中隊の補給物資を消費する。重戦車などは単位時間あたりの補給消費が大きいので早々に中隊の備蓄を食い尽くしてしまう可能性がある。中隊の補給物資の補充はランダムな時間(1~3日間に1回)行われるので戦闘を控えるべき場面も出てくるだろう。
 射撃システムも変更して完全に命中率、回避率、時間帯などの要素により確率で決まるようにした。例えば歩兵は森のなかでは回避率が高くなるのでダメージを受けにくくなる。このあたりは当初から目指していた仕組みでギャンブル性が高いターン制のシュミレーションゲームBattle for Wesnothをモデルにしている。以前より戦術からより戦略寄りになったといえる。
 スコアシステムも一応実装した。ユニットがダメージを受けるごとに予め設定されたスコアが失われ0になると負けになる。このあたりはWargameのDestruction pointを模している。スコアについては今後仕様が変わっていくだろう。


ちなみにUIの色を変えられるようにしたので1番上の写真のUIの色を変えて上のような色にもできる。今後は爆発のエフェクトなどを実装しクリスマスに原始的なベータ版のリリースを目指す。

2016年10月30日日曜日

【Unity】 Bwars 2 (RTS) 地形テクスチャの刷新

インスタンシングでのビルボードの表示ができるようになったので、これを機会にずっと借り物だった地形のテクスチャを作って刷新した。あわせてシェーダーも改良してゲームの見た目は以前よりずっと良くなった。


 テクスチャはPhotoshopで制作した。まあ適当に画像を重ねていけばなんとかなる。畑の部分はフィルターの「水晶」が役に立った。ボロノイ図的な絵柄ができあがる。



 街を近くで見るとこんな感じ。テクスチャを工夫して街っぽくしている。遠目で見るとそれらしく見える。木はビルボードだが雰囲気は良い。そもそもあまり拡大しないゲームなので遠目で見た目が良ければ十分だ。


 夕刻の様子。今後はAIの補給がややうまく行ってないのでそれを改善する。またスコアの仕組みも実装する。スコアは頭の痛い話でどういう勝利条件を決めるかも含めて思案中。

2016年10月20日木曜日

【Unity】 Bwars2(RTS) 街と遺跡と


前回のマス目に基づく補給システムは止めてしまった。変わって各所に配置されたフラッグ周辺でユニットは補給できるようになった。従ってユニットは昼間は戦闘を行い、夜はフラッグの近くに戻ることになる(キャンプファイヤーのようだ)。
 森に続いて街も実装した。まず適当な多角形で街の範囲を決めて塗りつぶし、そこにポアソンディスクサンプリングで家を生やしている。


動的に街を生成する方法もあるが、そこまで手がまわらないので後日の課題になるだろう。あわせて前のBwarsでもおなじみの廃墟も配置するようにした。地形は生成されるごとにランダムに変わる。こうした巨大構造物を置くのは僕の好みだ。


リング状の廃墟はベジエ曲線上に並ぶようにしてある。


今後は地形による射線の遮りを実装していく。

2016年10月8日土曜日

【Unity】RTS:補給と昼夜


 補給と補充、昼夜の仕組みを導入した。戦場はマス目に分割されて、昼の時点で自軍の占領が確定する。周囲に敵がいると占領できないので敵味方が対峙する前線のマス目は中立を維持する。ユニットは補給・補充を受けるためには朝の時点で自軍のマス目にいる必要がある。従って昼間は前線の中立地帯で戦い、夜には一旦後退して自軍のマス目に戻るというのが1日のサイクルになる。


 一日の時間に応じて照明の色が変わる。UIも改善して、多言語化に対応した。ユニットをマウスオーバーするとそのユニットがリアルタイムで表示されるようした。


 さらに改善したポアソンディスクサンプリングによって木を生やした(詳しくはここ)。木はハードウェアインスタンシングで描写している。

今後は地形の生成アルゴリズムの改善、グラフィックの改善を行う予定。

ポアソンディスクサンプリング (poisson disk sampling)


ゲームで木をまんべんなく生やしたいと思いポアソンディスクサンプリング(poisson disk sampling)を利用しようとしたが技術がないのでアルゴリズムの短い論文を読んで実装するのに非常に時間がかかったので、ここに要約を書こうと思う。ポアソンディスクサンプリングとは点同士が一定以上の間隔を保って面を覆うために使われる技法で、間隔を調整することで濃淡から絵を描くこともできる

論文の要旨

確定した点のリスト、将来性のある点のリスト、及び2次元のグリッドを用意する。確定した点のリストには最終的に出力される点、将来性のある点のリストにはその点を基準に更に点を配置できる点が入る。グリッドは点同士の距離を計算する際に計算を簡略するために用いられる。点同士の最低間隔をrとする。

1 まずランダムな点を1つ生成する。これは直ちに確定した点のリストに入る(1つ目の点だから)。同時にこの点は将来性のある点のリストにも入る(周りにはまだ1つの点もないのでこの点を基準に新しい点を生成できる可能性があるから)。 確定した点はグリッドに登録し点同士の距離の比較に備える。
2 この点を基準点とする。この点の周囲半径r~2rのリングに収まる範囲に新しい点を生成する。この点とすべての確定した点との距離を計測し、間隔が小さすぎれば(グリッドを利用し計算を簡略する)その点を破棄する。確定した点たちと十分な間隔がある点は確定した点リストおよび将来性のある点リストに入りグリッドにも登録される。こうしてリング内に均等に点を生成し続ける(10~30回程度)。この試みの後、もしリング内に生成した点がすべて確定した点たちとの間隔の不足から破棄されていれば基準になった点にはもう将来性がないということなので、この基準になった点は将来性のある点リストから除かれる。
3 次の基準点は将来性のある点のリストの最後尾にする。そうしてまた2の処理を行う。
4 将来性のある点リストがカラになるまでこの処理を繰り返す。

この方法で素早く点を生成しゲームで指定範囲内に木を生えさせた。


 この場合点は白黒のテクスチャ上で黒のエリアの部分に生成されている。黒の部分が複数あり互いに白で隔てられている場合、アルゴリズムの特性上一つの塊の黒の部分でしか点が生成できない。そこでまず大雑把に全体に点を生成し、その各々の点を基準に2度目の点を生成することですべての黒の塊に点を生成している。

2016年9月17日土曜日

【Unity】RTS:ゲームのセットアップと補給補充


 ゲームのスタートにあたりユニットの数や種類を設定できるダイアログを仮実装した。コストにあわせてランダムに精度悪く自動で編成することもできる。


 地形の仕組みも刷新して浅い森や深い森などを生成することができるようになった。


 補給や補充の仕組みついて迷いがある。そもそもこの仕組みを導入しようと思ったのは、一旦戦端が開かれると絶えず戦闘が続くことによりプレーヤーに過度なストレスを与えることを避けることだ。またこうなると最初の衝突から延々と消耗戦が続いくことになり最初の戦闘部隊の配置以外に作戦を立てる余地があまりなくなってしまい面白みは半減する。そうしないためには戦闘はある程度行われると終了して、戦闘の結果を踏まえ作戦を練り直し戦闘部隊を再配置する「休憩」の時間が与えられるのが望ましい。戦闘と休憩を繰り返し行うことでゲームが進行することが理想だ。これを実現するためにはなんらかの形で戦闘を制限する仕組みがいる。
 現実の戦闘においても戦闘部隊が絶えず戦い続けることはない。戦うと弾薬や燃料を消費し疲労が蓄積し装備は消耗する。そのために戦闘を中断して補給を受ける必要がある。夜は暗く戦闘には不向きだから補給に適した時間帯といえる。
 ゲームにこの仕様を組み込むことについていくつかのアイディアがある。

1)補給圏を設置して補給のためには最前線から引き上げる必要があるようにする。補給圏を囲む補給線は最前線の前進に伴ってその後方において前進する。
2)グローバルな補給可能な時間帯を定める。ごはんの時間になるとみんな遊ぶのを止めて家に帰るようになる。
3)戦闘ペナルティがつく時間帯を設定する。攻撃速度や射程が低下し弾薬の対効果が悪くなる。

 補給線の移動のルールはよく考える必要がある。戦闘部隊の平均位置から決めるのは合理的に見えるが、素直に従っていると戦闘部隊の大半が補給のために後退するとその分補給線も後退してしまう。どの時点で補給線を更新するかが鍵だ。昼夜の概念を取り入れたらいいのかもしれない。夕方の時点での前線を基準にするとか。夜のうちに戦闘部隊は補給され朝には最前線に復帰している。そして夕方まで戦い新たな前線を勝ち取る。
 補給・補充(ヒットポイントの回復)と攻撃力のバランスにも慎重になる必要がある。前提としてユニットがポンポン死ぬようなバランスは避けたい。多くのユニットが必要になるからだ。もともと戦略よりのゲームにしたいという気持ちがあり、ユニットを大事に使うようにしたい。この場合弾薬を消費して敵に打撃を与えてもたっぷり補充されて翌朝ピンピンしているようでは戦闘の意味がなくなってしまう。従って補充は限定的なものであるべきだ。翌朝には場合によっては前線を維持するために消耗したユニットを投入する必要に迫られるだろう。補充の限界とはユニットのHPが最大値まで回復しないことかも知れない。最大HPからの差分の6割しか回復しないとか。あまりに傷ついたユニットは前線のはるか後方に後送し、一定時間後にフルに回復したユニットを手に入れられるようにすれば敵のユニットを消耗させると一時的に敵の前線戦力を減少させ前線を前進させることに繋がるようになる。前線を前進させるには相手を病院送りにすることが大切になるのだ。
 より作戦の幅を広げるためには前線を前進、あるいは後退させることにそれぞれメリットがあるべきだ。一般的には戦力が消耗した側が前線を後退させることになる。一方で戦局を有利に進めている場合は前線を前進させるだろう。前線の後退には防御に関するメリットが、前進には攻撃と勝利についてのメリットが必要になる。勝利については勝利条件を定めれば十分だろう。後退には補充の最大値が上昇するようにする。前線の前進は直接の効果はないが、拠点を制圧することでより多くのポイントを得、支援を得られるようになる。前線のより深い前進に対して補給線の追随が鈍くなるのはいいかもしれない。急速な前進を行うと補給線が追随せず補給が困難になる。補給線が追いつくまで踏みとどまるか撤退する必要が出てくる。
 こうした補給・補充の概念を導入した場合の懸念点は操作が煩瑣になることだ。自動化があったほうが良さそうだ。細かいことは忘れてひとまず全ユニットが一旦補給線まで後退する機能と翌日昨日の位置まで戻る機能は実装してもいいかもしれない。
 夜間はユニットが休むのでやや手持ち無沙汰になる。その間に翌日の支援を予約できるようにしたらいいかもしれない。支援とは砲撃や航空支援、ユニットの追加、一定エリアに攻撃・防御などのボーナスを適用するなどが挙げられる。

2016年9月8日木曜日

【Unity】RTS:ユニットのUI


 各ユニットのタイプごとにアイコンを作成してユニットの状態を示すUIを実装した。UIはユニットの種類とHP、戦闘継続時間を示している。


UIを作るのは楽しい。


また合わせて射程円とユニットの移動先を示す矢印も実装した。
今後は操作ボタンの実装を進めていく。

2016年8月26日金曜日

【Unity】RTS:戦闘継続時間


 HPの他に戦闘継続時間という仕組みを導入した。ユニットはこれにより一定の時間しか攻撃ができず、その後はクールダウンする必要がある。このため戦闘にかならず小休止が入るようになり常に戦闘しているという状態はなくなった。


2016年6月18日土曜日

【Unity】RTS ランダムな地形の自動生成


 ランダムに地形を生成するようにした。テクスチャは地面っぽく見えるように3種類を掛けあわせて適用している。


 デプスをとってグラデーションを適用している(遠くの紫、青)。このあたりは「王立宇宙軍」を見てて思いついた。



 地形のそれぞれのテクスチャはマスクをかけて表示するところを限定している。このマスクのために不思議なノイズを生成する仕組みを実装した。パラメータを変えるとノイズがかわる。



 これをもとにシェーダーでマスクをかけている。
また木も生成するようにした(まだテクスチャがないので白色)。木はGraphics.DrawingMeshを使って表示している。木の位置を決めるために木のエリアでポアソンディスクサンプリングを行っている(木同士が重ならないように配置する)。


 建物なども配置したいが時間がないのでベータ版には間に合わないだろう。今後は再度ゲームロジックに立ち戻って実装を続ける。




2016年6月5日日曜日

【Unity】 RTS UIとフラッグ、カメラの移動


 ユニットのUIとしてHPゲージと有効射程円を表示するようにした。射程円を示すにはプロジェクターを使っている。UnirXを部分的に使い始めた。HPゲージはリアクティブプロパティを利用している。上の写真はexeとして書きだしたゲームで旧いPCでもスムースに動いているようだ。


 カメラの挙動を改善してWASDによる移動に加え、中ボタンでぐりぐり回転できるようにした。スクロールで拡大縮小。スクロールはユーザーによってスピードがかなり異なるので適切なスピードで動くようにする必要がある。


 ユニットが占領可能なフラッグを実装。指揮官AIはフラッグを考慮に入れて戦線を設定する。明日からは地形の改善を行う。

2016年5月29日日曜日

【Unity】RTS:ユニットを増やす


 軽戦車・中戦車・重戦車・指揮車・歩兵を追加してユニットの数を増やし始めた。


ユニットや武器、砲弾の設定の大部分は外部XMLファイルで設定するようにした。これらを読み込み、反映させ、必要に応じてユニットを生産できるように新たにユニットパーツ工場とユニット組立工場を作った。これらの工場は初期化時にユニットの雛形を作っておき、発注があり次第ユニットを生産できる仕組みになっている。

2016年5月19日木曜日

【Unity】スペック値の操作


 ユニットのスペック値(防御力やスピード)を一時的にブースト(増大させたり減少させる)のは結構めんどうだ。一定時間内だけブーストがある場合はその時間が過ぎたら加減算された分だけもとに戻さないといけない。複数のブーストがかかっている場合は他のブーストに影響を与えないように気をつける必要がある。また時間だけでなく他の要素でブーストが無効になる場合もある。例えば集団でユニットが移動する場合、一番遅いユニットの速度に合わせるようにユニットすべての速度にブーストがかかるが、そのユニットが移動集団から離脱した場合は本来の速度に戻るためにブーストは無効にされなければならない。

 いろいろ考えた結果、ブーストチケットを発行することにした。このチケットはブーストの内容と有効時間、チケットIDを含み、あるクラスで集中管理される。有効時間が過ぎるとチケットは破棄される。一方そのブーストが適用されるユニットにはチケットIDが与えられる。ユニットは毎時間ごとに自身のもつチケットIDに該当するチケットがないか問い合わせて該当するチケットがあればそのブーストを適用する。また予めチケットIDを破棄する条件を決めておいてその条件が満たされるとチケットIDは破棄される(例えば新しい移動地点が設定された場合など)。

 延々とAIの開発を続けてきたが、一段落ついたので今後は別の種類のユニットを追加して改良を加えてみる。

2016年5月6日金曜日

【Unity】RTS:指揮権の分割


 プロジェクトは着実に、のろのろと進んでいる。前回書いたように指揮官AIの権限の一部を新たに数個のユニットを指揮するチームAIに移すことが出来た。この結果指揮官AIはどのチームを何処に移動させるかという点にのみ集中できるようになった。不完全ながら複数のユニットを横隊を組ませて展開できる機能を追加したので、チームAIはそれを利用してユニットに移動命令を出せるようになった。さらにバグっていたユニットが他のユニットを回避する機能を修正してうまく動くようになった。上の写真ではうまい具合にレッド軍が敵を半包囲攻撃することに成功している。


また指揮官AIの権限を変更できるようにしたことで軍の指揮権を指揮官AIからプレイヤーに、プレーヤーからAIに委譲することが容易になった。これは将来役立つだろう。AIはあくまで戦線に応じてチームを動かすので、あるチームが窮地に陥ったときに他のチームに救助を命じること出来ない。また今のところ同種のユニットしか使っていないので様々なユニットを使った場合の挙動が気にかかる。その辺りを退治してくことになるだろう。

2016年4月19日火曜日

【Unity】RTS:前線の拡大縮小



形成される前線点への戦力の割当を改善した。パラメータによって前線の位置に応じて戦力の分配度を調整できる。これで例えば前線が自陣に近い時は戦力を集中して守りを固め、遠い場合は戦力を分散して半包囲攻撃を目指すというようなことができる。あわせて前線の位置から前線の幅も変わるようにした。前線が中央にある時は下の写真のように幅が広い(丸い点とそれを結ぶ線が前線)。


 一方でどちらか片方に前線が偏ると幅が狭くなる。このため守備側も攻撃側も無駄なく戦力を集中することができる。


こうしたパラメータは変更可能なので指揮官ごとに性格づけることができる。

 前にも書いたかも知れなけど、指揮官AIの状況判断は各ユニットからの情報を吸い上げて分析した情報で判断する以上、どのような処理をどのタイミングで実行するかがとても大事になる。そのため1ユニットに至るまでどのような処理を実行するかは中央で管理したほうが都合がいい。これはスター・ウォーズでの司令船とバトルドロイドの関係に似ている。大局的な判断はドロイドから収集した情報を元に司令船が行い、ドロイドはその命令に応じて個々の処理を行う。司令船が破壊されるとドロイドは動かなくなる。

 いまAIは指揮官AIとユニットのAIの二つがあるが、実際にはユニットは数個で1つのチームとして扱われているのでチームAIを新たに作り指揮官AIの一部の権限を以上することを考えている。こうすることでよりチームが一丸となって行動できるが、一方でユニットの行動により深く介入することになるので、ユニットAIとの機能衝突が起きる可能性が高くなる。

2016年4月9日土曜日

【Unity】RTS:地形など


 前回から手動で拠点を設定し(まだ手動)前線点がそれに引きずられるようにした。またマス目ごとに地形を規定するようにした。緑の部分が森を示している…たぶんそこに木が生えるようなるだろう。地形を捜査するメソッドも実装してユニットは一定距離内のある程度定まった方向の地形をスキャンできるようになって防御に適した地形を発見できるようになった。今後はユニットが移動目標地点を予約して混雑を防ぐようにする。



2016年3月29日火曜日

【Unity】RTS:前線への部隊配備


 前回の両軍の影響範囲を計算するマップを使って前線を設定し、ユニットを配置することに成功した。ユニット情報が更新されると影響マップ作成され、各指揮官AIはそのマップをもとに適当な数の前線点を設定する。前線点の位置に応じて要求戦力が決められ、優先度の高い前線点から複数のユニットから構成されるチームが割り振られていく。下の写真では左からのブルー軍と右からのレッド軍がマップ中央で対峙している。ブルー軍のほうがやや戦力が優越しているので影響範囲が広い。


しばらくするとレッド軍が優勢になりブルー軍を追いやってしまった。


 戦術の決定の仕方も改め、まず指揮官AIがチームの状態を確認した上でチームごとに一番攻撃的な戦術の上限を決定して、ついで各ユニットが自身の状態に応じてチームの戦術の上限を超えない内で戦術を決定して振る舞うようになった。これで一応AIによる最低限の作戦行動が可能となった。

 現在は両軍の戦力とその位置によってのみ前線が決定しているので、今後これに地勢上の拠点による重みを加味するように改善していく。

2016年3月23日水曜日

【Unity】RTS:戦況マップ


このあたりを見ながらほそゞゝとAIが判断材料とする戦況マップを実験している。青丸と赤丸が部隊の位置で距離に応じて影響度が低下する。黒い部分は両軍の影響力が拮抗しているか、ない場所を示している。基本的に黒い戦線が遠ければ進軍する…という方法がとれそう…と考えている。

2016年3月12日土曜日

【Unity】RTS:AI


 引き続きAIを作っている。撤退したユニットが司令部近くで回復できるようにしたのでAI同士の軍勢が押し合いへし合いするようになり見ていて面白くなった。 近い目標地点には微速で移動しながら回転したり、退却時の移動を最適化。ここに来てこつこつ作っていたユティリティクラスが役に立ち始めた。例えば指定地点まで移動するのにかかる時間を返す関数は複数の移動先の選択肢から最適なものを選んだりするのに幅広く役立っている(単に距離をスピードで割っているだけだが)。他にもある地点は何時方向になるだの、何時方向にいくら移動した地点はどこだのといったことを調べる関数が役立っている。戦術的に正しい動きを実装する上でストレスなくアイディアを表現できるのは嬉しい。
 当然といえば当然だが、機能と思考を徹底的に分離して実装することが大切だと常々感じるようになった。例えばシャーシクラスはユニットの移動を担当するが、あくまで目標地点まで円滑に移動するだけの機能しかない。ユニットがダメージを負って退却するのを命令するのはユニットAIクラスだ。またシャーシクラスには近隣の味方を発見して回避する関数があるが、自身で発火させることはない。これもユニットAIクラスが適切なタイミンで発火させる。もし自動で回避するようにしていたら敵前で横っ腹を向けるような運動をしかねないからだ。このように各機能はあくまで命令を与えられた時のみ稼働して最適な方法で目標を達成することにとどめ、一つの思考をもったクラスで各機能を集中管理・使用するのが望ましい。