2017年7月28日金曜日

【Unity】RTS : Bwars 2 ゲームループ

 
死んだ戦車が黒色になっている

セクターを実装し、データファイルから生成されたセクターの制御点にユニットを置くとセクターを占領できるようにした。まだ効果はないが産出するスコアや補給量の指定もできるようになっている。またデバッガークラスを開発して様々なクラスから気軽にギズモやテキストを表示できるようにした。これは今後の開発に役立つだろう。
 
セクターごとの制御点の有効範囲が赤の円で示されている

 ゲームループ(ゲーム中に実行される定期的な処理)は3つに落ち着きそうだ。一つ目はごくごく普通のUnityの毎フレーム呼ばれるUpdateでここでユニットの移動や砲塔の回転などを行う。二つ目は1秒毎に実行される処理でセクターの占領状況やスコアの更新を行う。最後が不定期な処理でここでは全ユニットのステータス更新・索敵の実行とその最新の状況を分析したAIによる指揮処理を行う。不定期なのはAIの処理が終わるのを待って次の更新を行うからだ。このAIの処理は別スレッドで実行している。今のところパッシブな役割の火器管制AIのみだが、これに能動的にユニットを動かすいわゆるゲームAIが加わるので処理時間は長くなるだろうがそれでも1秒以内には収めたい。

2017年7月18日火曜日

【Unity】RTS : Bwars2 ゲームのルール

 地形やセクターの生成ができるようになったので、今はユニットの性能を基本の値から上下させるブーストシステムを作っている。このブーストの例としてはあるセクター内のユニットの移動速度が上昇したり、特殊ユニットの近くにいるユニットの武器の命中率が上昇することなどが挙げられる。ブーストは基本的にある条件を満たす場合のみ適用され、条件が満たされなくなると効果は取り除かれる一過性のものだ。これはなかなか難しいもので旧プロジェクトでも実装時にあれこれ考えたことがある。上の例に沿うとあるユニットがあるセクターに入ったときに速度を上昇させ、出ていったときにその上昇分の速度を取り除く必要がある。そこで今回はブーストのチケットを発行し、適用対象のユニットに渡して以後条件が満たされ続ける限り同じチケットをユニットに渡し続ける仕組みを考えた。ユニットの方としてはチケットを初回に受け取ったときにブースト効果を適用するとともにチケットを保存し、以後同じチケットが来る限りなにもしない。チケットが来なくなったら保存していたチケットの効果を取り除きチケットも破棄する。この仕組によって後に書くようなセクターやヒーローによるブースト効果の仕様を実現しようと考えている。

 前回のプロジェクトが破綻した理由の一つは制御系と操作系のプログラムがくっついてしまったことだが、他にも大きな要因としてゲームのルール・方向性が決めきれなかったことがある。今回いろいろ考えて、新しく以下のような仕組みで行こうと考えている。

セクター
セクターは戦場を複数のエリアに区分けられたもので戦場のあらゆる地点はどれかのセクターに属している。セクターでは補給物資が産出されるが、あまりの多くのユニットを1つのセクターに配置すると補給物資を食い尽くしてしまい、ユニットは行動にペナルティを受ける。1つのセクターは1つのコントロールポイントを持つ。コントロールポイントにユニットを移動させることでセクターを占領でき補給や戦闘などでセクター内の友軍ユニットがメリットを受けることができる。

エース
前プロジェクトでは指揮官は複数のユニットを管理する立場としたが、今回は1ユニットを指揮するエースとしての立場を考えている。位置づけとしてはWarcraftのようなヒーローユニットのように自身の戦闘や周囲のユニットになにかしらのブーストを与える。ユニット自体をエースとしてもいいが、キャンペーンを想定した場合ユニットの技術ツリーなどを考えないといけなくなるので、あくまであるタイプのユニットに搭乗(指揮)できる独立した個人を考えている。例えば第2次大戦でティーガー重戦車で多くの戦果を上げた戦車乗りオットー・カリウスを考えたら分かりやすいだろう。

勝利条件
勝利条件はいくつか設定できる。代表的なものはスコアでユニットの撃破やセクターの占領維持で得られるスコアで相手を上回ると勝利となる。他には特定セクターの占領や特定ユニットの撃破が条件になる。勝利条件がスコアのみ場合は様々な方法でスコアが稼げるのでいろいろな方法で勝利が狙えるようになるだろう。


2017年7月12日水曜日

【Unity】RTS:Bwars2 外部からの火器管制


動的にユニットと地形を生成し、移動・戦闘が出来るようにした。今回のプロジェクトの一番重要な目標はコアとなるクラス群は必要最小限のゲーム進行しか担当しないということにある。これは地形の生成においては地形データを画像を始めとするデータを与えることで仕組みで叶えている。上の写真は予め準備した画像を与えて地形を生成させた結果を示している。コアクラス群において地形のデータ自体を生成することはない。ユニットの生成についても前回の投稿の通りJSONデータにより生成しているがここで少し詰まった。当初、最初にユニットの雛形を作成し、ユニットが必要になった時点で雛形をInstantiateしてユニットを複製する仕組みを作った。ユニットの基本性能値はユニットの種類ごとにおいて共通だから別途MonoBehaviourを継承しない普通のクラスで性能値を定義し、個々のユニットを管理するクラスに紐付けることで個々のユニットの性能を定義しようとした。しかしInstantiateはコンポネントしか複製しないようで、雛形でユニットの管理クラスに紐付けていたはずの性能定義クラスはそのユニットの複製品ではリンクが切れていた。仕方がないので複製後に性能定義クラスを紐付けることにした。


 今回コアクラス群では最低限のことしかしないのでユニットのどの武器を使ってどの敵を攻撃するかは別途命令してやる必要がある。ユニットの管理クラスは攻撃面においてはユニットが所持する武器と補足した敵の情報を与えるメソッドと個々の武器に攻撃目標を割り当てるメソッドを提供しており、これを利用して攻撃の指示を出すことが出来る。本プロジェクトでは必要な情報を提供し、命令を受け取る機能を用意すればコアの外部からでも十分操作可能であるはず、という考えを採っている。そこで攻撃範囲に入った敵を攻撃するというパッシブな外部AIを作成してうまく動作させることが出来た。これは前のプロジェクトではユニット管理クラスに内蔵されていた機能で、このために操作と処理の機能が混ぜ合わさりどうにもできなくなっていたが、本プロジェクトではそれを分離し操作は外部からすべて行うことで解決しようとしている。この火器管制AIの成功は本プロジェクトの指針が正しいこと示しているように思える。