近くの敵を優先して攻撃し、撃破したら次の敵へ向かうAIを作ってみました。
画面上にタッチすると、味方の戦車を配置します。戦車には射程距離があり、攻撃範囲では停止して相手へ射撃します。
このAIは、Clash of Clansのアーチャーやウィザードなどの動きを想定して作りました。
(あと、Clash of Clansには範囲攻撃と非範囲攻撃の差があります)
一番近い敵を探す。原始的なコードですが(ゝω・
コライダを使って、範囲内のGameObjectを距離に応じてソートして取得みたいなやり方がありそうですが、結局ロジックは同じですし(*´ω`*)
int targetNo=-1; float minDis=9999f; float dis=0f; for(int i=0;i<=3;i++) { target = Main.targets[i]; if(target == null ) continue; dis = Vector3.Distance(transform.position,target.transform.position); if(dis<minDis) { minDis=dis; targetNo=i; } } if(targetNo==-1) return;
相手の方に徐々に向く
transform.rotation = Quaternion.Slerp( transform.rotation, Quaternion.LookRotation(target.transform.position - transform.position), Time.deltaTime*10f);
相手に近づく
transform.position += transform.forward * Time.deltaTime;
射撃はコルーチンで行います
private IEnumerator Shoot( float interval) { for(;;) { GameObject b = Instantiate (bullet,transform.position, transform.rotation) as GameObject; b.GetComponent<Bullet>().target = target; yield return new WaitForSeconds (interval); } }
弾を生成し、ターゲットを教えます。
弾側は、上記と同じようにターゲットに向きつつ近づきながらトリガー発生で自壊します。
ターゲット側は、弾が当たったらダメージを食らってHP0以下なら破壊されます。
ここで爆発エフェクトなりの演出を追加すればいいです。
void OnTriggerEnter(Collider col) { if(col.name.Substring(0,6) == "Bullet") { hp-=100; Debug.Log("damage:"+hp); if(hp<=0) Destroy(gameObject); } }
次の題材です
途中で、ターゲットが左右に2つ残ったとき、近くのターゲットに向かうというロジック上、左上に1台、残りは全部で攻撃を行いました。トータルでの攻撃完了時間で考えると、左上のターゲットには複数台で向かうべきでした。
一番近くという評価だけではなく、ターゲットを取っている友軍が多い方には行かない(向かうと移動中に撃破して無駄になる可能性が高い)というロジックを入れたほうがいいです。
Clash of ClansのAIの場合は明らかにその評価が入っていますね。
最短ではなくターゲットをとってない敵を優先して狙うというロジックを逆利用した技が、Clash of Clansだと「サイドカット」と呼ばれています。
www.youtube.com
あと、今後追加したいのは、敵との間に壁がある場合に、壁をさけて回避路を選んだり、壁を破壊したりする最短経路探索ですね。
壁は壊せるので、回避する時間的コストと壊すのにかかるコストを比較して行動選択する必要があります。
味方がいるので壁破壊コストは射撃中の援軍の数によっても変わってきます。
このへんがおかしいと、壁殴りのような現象が生じます。