2013年3月11日月曜日

見回りをする敵の作成

よくある雑魚敵.
見回りの兵士しかり, ただ歩く雑魚しかり, よくある敵の動きとして決められたポイントを動く敵の動きを組んでみた.
作った段階順にメモメモφ(・ω・ )

見回り兵の動きの作成

1. ターゲットの方を「向く」

今回考えたのが, ターゲットの方を向く → 前進! でシンプルにいけるんじゃね?ということ.
なのでまずは「ターゲット」としたものの方を向くことから
var speed : int;
function walkToTarget(t:Transform){
 var targetVec : Vector3 = t.position;
 targetVec.y = this.gameObject.transform.position.y;
 gameObject.transform.LookAt(targetVec);
 this.transform.Translate(0,0,1 * speed * Time.deltaTime);
}
6行目はまだ見ないで('A`). 引数の tは目標の transform. speedはお好みで. ここに出しておくと Unityの Inspectorですぐいじれるから便利.
3行目で目標の positionを取得. これをtransform.LookAt()に放り込むだけで, 引数に入れた positionの方を向いてくれるから便利. ただしこのままだと, 目標が自分より高い位置にいる場合, 最悪仰向けになるという間抜けさ.
なので 4行目, 見る positionの高さ yを自分の高さにしてやれば, 不自然に仰向けうつ伏せになることはなくなる.
これをUpdate()のなかで呼んで, とりあえず目標の方に「向く」ことができた.

2. 「前進」する. 

わりと大事だと思ってる. 適当な区間を歩かせようとしたとき, 「ここから x歩いたら y度修正して 半径 rの弧のうえを歩くように…」なんて考えたくない('A`) できる限り楽したいのです.
this.transform.Translate(0,0,1 * speed * Time.deltaTime);
さっき見えちゃったけど. transform.Transrate()の引数に Vector3で動く量を指定してやるだけ.
今回はただ前進したいので zだけ増やして残りは 0. speedは1. の通りお好み. Time.deltaTimeはフレームレートの違いを吸収して, 単位時間当たりの変化量を一定にしてくれるらしい. 端末の違いなどで変化が出ないようにするのに非常に役立つ.

ここまでで, あとは適当なところで目標を指定してやれば, そいつを追い続ける動きができる. がそれだと巡回ができない.
なので「巡回のポイントごとにマーカーを置き, そこに到達したら次の目標を指示する」ようにしてやる.

3. マーカーの作成

イメージはカラーコーンか. こいつを作る前に, 1. 2. を載せる敵に Enemyのタグをつける. これで「巡回中の敵がマーカーにたどり着いた」を識別する.
まずはマーカーの GameObjectの作成. これは何でもいいけど, 必ず敵が「到達」できるようにすること. はるか上空にあるマーカーを眺めて荒ぶる兵士とかかわいそうすぎる(;ω;`)
適当に cube当たりをチョイス. 名前を checkPoint1とでもしたら Inspectorを見る.
見えているマーカーを回るならともかく, 基本は何もないだろうし, Mesh Filterの Meshを Noneに. 
Colliderは Is Triggerをチェックしておく. 
こうすることで「トリガー」となり, 物理的な当たり判定が消え, 物が素通りするようになる. 
ただし「衝突した」ことはとれるので, センサーなど目に見えない範囲を作るときに重宝する. 
今回もその恩恵にあやかる. 
準備ができたらスクリプト.
var nextTarget : GameObject;

function OnTriggerEnter(object:Collider){
 if (object.gameObject.tag == "Enemy"){
  object.gameObject.SendMessage("changeTarget",nextTarget);
 }
}
OnTriggerEnter()は引数の「なにか」がトリガーに引っかかったぞ, というメソッド. 何がトリガーの範囲に入ってきても呼ばれる. なのでふるい分けをしてやる.
4行目は, 入ってきた「なにか」のタグを取得し, if文でふるい分ける. 今回は敵が巡回してきたら反応したいので, タグは Enemy.
Enemyが来たらそいつに対し, 5行目の処理. 内容はぶつかってきた objectに対して, 「changeTargetというメソッドを, nextTargetという引数を与えて呼び出せ」ということ. これまた便利.
あとは nextTargetに次に目指してほしいマーカーを入れてやるといい.

4. 目標切り替えの処理

これは単純
var target : GameObject;
function changeTarget(newTarget:GameObject){
 target = newTarget; 
}
これだけ. これを敵の方のスクリプトに持たせる. マーカーではない. このメソッドを持ってマーカーに突っ込むと, 次の目標の支持が飛んでくる寸法.
最後に Inspectorから, 「一番最初に向かう目標のマーカー」を敵の scriptの targetのところに指定してやればいい.

ちなみにこの指定の際,  targetをフィールドに宣言していると, Hierarchyに並んでいるマーカーを, Inspectorの scriptの中に表示されている targetにドラッグ&ドロップしてやるだけでいい.
どこを指定したかがわかりやすいかと.

5. マーカーをばらまく

マーカーをコピーしてばらまくだけ. もちろん「次の目標」はそれぞれに設定しないといけないけど.

これで「適当なポイントを巡回する兵士」みたいな動きができる.
ただこのままだと怪しいやつが目の前を通っても無視するおバカ兵士になってしまう.
のでその辺を足すとより敵っぽくなるかと.




ながなが書いたけどコードにするとめっさ短いのがUnityのいいところ. ∩( ・ω・)∩




0 件のコメント:

コメントを投稿

AWS CDKで立てたEC2インスタンスのTimeZoneとかいじりたかった話

EC2を立てることはできたけど、立てたインスタンスは UTCのままだし設定ファイルとかいちいちscpしてくるのはダルい。 当初UserDataでなんとかしようとしたものの、「書く量がヤバいしメンテしにくい」と悩んでいたところ見かけたのが  AWS::CloudFormation:...