昨日のSDユニティちゃんで学んだNavMeshをAIタンクに適用してみました。
まずマップにNavigationをbakeします。
ランダムに画面上にターゲットを配置。
画面上にクリックした位置にAIタンクを配置できます。
タンクは近くのターゲットに対し、
agent.SetDestination(target.transform.position);
で移動開始。
ターゲットとの距離が射程範囲、かつ、視界に壁が無い場合に停止して射撃開始。
if( flag && dis<=8f && dot>=0.97f && !Physics.Linecast(transform.position, target.transform.position) ) { agent.Stop(); status="ATTACK";
dotは内積です(内積が1に近いほど相手が自分の正面にいる)
射撃時は停止したいので、Stop()で経路上で一時停止します。Resume()で復帰できます。
ちゃんと正面から射撃をしないな? と思ってたら内積計算が間違ってた。
float dot = Vector3.Dot(transform.forward, target.transform.position - transform.position );
正しくは以下。
内積=|a||b|cosθなので、正規化しておかないと-1~1にならないので dot>=0.97fって条件が正しく動かない。
float dot = Vector3.Dot(transform.forward, (target.transform.position - transform.position).normalized );
近いターゲットの判定はpathの累積距離を求めてますが、pathPendingがtrueの場合は、単純に距離を求めています(壁を突き抜けているので不正確)
このへんは非同期処理になるんで、ちゃんとやるとちょっと複雑ですね。
では、実際の索敵・攻撃の様子。NavMeshすごいですね。壁にはめり込まないし、マップからは落ちないし
NavMeshObstacleの仕組みがあるので、やろうと思えば動的にマップを作れそうですね。壊せる壁とか。
NavMeshAgentのRaycastを使ったほうが良いようです
tsubakit1.hateblo.jp