Pages

2013年6月10日月曜日

ロックオンの処理

やぁ、諸k(ry


ゼルク・ハーデスだ。


この連休中、プレイヤーが敵をロックオンをする

といった処理を考えて実装してみた。

が、これがかなりの鬼門であった。

まずは1体だけロックオンをし、ロックオンをした場合その敵の方をずっと見て動く
という処理だ。

プレイヤーにスフィアコリジョンを持たせ、isTriggerにチェックを入れておく。
OnTriggerEnter(Collider c)関数が呼び出された時、
c.gameObject.tag == "Enemy"だったら変数targetにcをぶち込めばいい。
そしてIsLockOn()でターゲットとの距離がtargetDistance(ロックオン可能距離)よりも近くて、ボタンを押されたらロックオンを可能にする。これはフラグを使った。
フラグがONになるとロックオン専用の動きをするようにすればいい。

ターゲットとの距離がロックオン可能距離を越える。またはONの状態でボタンを押されたらフラグをOFFにすれば通常モードになる。


敵一体の場合はとても簡単に実装ができた。

しかし、次が問題である。
たいていのゲームの場合、ロックオンの切り替えが可能になる。
◎機能
・ロックオン時、指定のボタンを押したら次に近い敵にロックオンを切り替える。
・ロックオンしている敵がロックオン可能距離から離れた場合、次に近い敵にロックオンを切り替える。
・ロックオン可能距離に複数体いた場合、可能距離に入った順ではなく、一番近い敵にロックオンをする。

だいたいこの3つであろうか。

さて、複数の情報をどう管理するか・・・配列か・・・
Dictionaryを使う方法もあるかもしれないが、私はLinkedListという配列(?)を使った。
LinkedListやDictionaryをUnityで使う場合、using System.Collections.Generic;を書かないと使えない(javascriptはわかりません)
LinkedList<GameObject> targetList = new LinkedList<GameObject>();と宣言する。
OnTriggerEnterでtargetList.AddLast(c.gameobject)とする。
どこかでtarget = targetList.First.Value;
こうすればスフィアコリジョンに入ってきた順でロックオンが可能になる。
しかし、それでは2番目に入ってきた奴のほうが最初のやつより近かった場合、ロックオンが2番にできなくなる。SetListという関数で並べ替えをする。
私は
LinkedListNode<GameObject> node = targetList.First;
  while(node != null && node.Next != null){
   if(Vector3.Distance(transform.position,target.transform.position) >
    Vector3.Distance(transform.position,node.Next.Value.transform.position)){
    GameObject temp = node.Next.Value;
    targetList.Remove(node.Next.Value);
    targetList.AddBefore(node,temp);
    break;
   }
   node = node.Next;
  }
とした、現在のターゲットより、その次の奴のほうが近かった場合、targetListの中身を入れ替える処理だ。
※これだと3体以上になったときに多分うまく行かない。後々調節する予定。
※追記:以下に書き換えた事により、3体でも上手く動作した
 LinkedListNode<GameObject> node = targetList.First;
  while(node != null){
   LinkedListNode<GameObject> node2 = node.Next;
   while(node2 != null){
    if(Vector3.Distance(transform.position,node.Value.transform.position) >
     Vector3.Distance(transform.position,node2.Value.transform.position)){
     GameObject temp = node2.Value;
     targetList.Remove(node2.Value);
     targetList.AddBefore(node,temp);
    }
    node2 = node2.Next;
   }
   node = node.Next;
}
しかし、この処理はたぶんすごく遅いと思われる。


こうしておけば一番近いものがtargetListの最初に常におかれる状態になる。
あとばボタンで切り替える処理だ。
if(target == targetList.First.Value && targetList.First.Next != null)target = targetList.First.Next.Value;
else target = targetList.First.Value;
targetにファーストが入っており、かつ2番めがNullじゃなければ2番めをターゲットにする。
これはあとで改良するつもりだ。3番目に辿りつけないからである。

こう問題もまだ残っているが大体形になってきた。


さて、次はタイトルシーンなどを考えてみようか。



アリーヴェデルチ。

0 コメント:

コメントを投稿