Unityでアーマードコアっぽいロックオンを実装

アーマードコアVにでてくるようなロックオンシステムを実装していきます。
画面に描画されたロックオンサークル内に、敵を一定時間捕捉しているとロックオンしてくれるシステムですね。

こんな感じ↓(画像は拾いもん)

以下のようなロジックでロックオンを実装していく。

※最初の画面内に敵がいるかどうかの判定は不必要かもしれない

OnWillRenderObject関数は指定したカメラに映る位置にオブジェクトがいた場合に呼び出される関数。まずはここで自機の視野角内にいる敵に絞り込む。

しかし、OnWillRenderObject関数はカメラと対象オブジェクトの間にある他のオブジェクト有無を考慮しない。
つまりこのままでは壁の向こう側にいる敵すらロックオンしてしまう。

なので、Physics.Linecast関数を用いて間に他のオブジェクトが間にあるかの判定を行う。ここで全オブジェクトを判定にいれてしまうと弾が自機と敵の間を通っただけでロックオンが途切れかねない。なので有無判定を行うオブジェクトにはレイヤーでマスクをかけること。

上記の手順で実際にプレイヤーから見て画面上に移っている敵に絞り込まれるはず。後は絞りこんだ敵が画面上のどこに描画されているかをRectTransformUtility.WorldToScreenPoint関数を用いて取得する。
RectTransformUtility.WorldToScreenPoint関数は指定したワールド座標を画面座標に変換してくる関数です。
敵の画面座標が分かったのでこの画面座標がロックオンサークル内に収まっているかを判定する。
ロックオンサークル内に何フレーム捕捉し続けているかを計測し、目標時間まで到達したら晴れて無事ロックオン完了といった流れ。

各関数の細かい使用方法や注意点は、ぐぐれば個別に詳細がわかる記事があるのでそちらを参考にしてください。

上記を踏まえ、以下のように実装しました。

敵の画面内に入っているかの判定

ロックオンシステムの処理

ロックオンマーカーは以下のように実装
あらかじめ以下のような画像を用意し、スクリプトイメージとしてインポート
白い長方形の辺部分の画像なので、背景白いからなんも見えないかも・・・

※インポート時にTexture TypeをSpriteにすること
これをUIのImageとして描画し、スクリプトで描画位置と色・表示非表示を処理している。
UIに関しては以下が参考になりました
http://www.metalbrage.com/UnityTutorials/uGUI/ImageElement.html

あとはロックオンしたら武器の向きを
transform.LookAt ()で敵に向けるだけ。

こんな感じになりました。

まだ偏差撃ちを実装していないので、ロックオンするとむしろ当たらない・・・

望み通りの動きになってはいるものの、カメラの視野角に収まっているかどうかの判定処理を敵オブジェクト自体に入れなきゃいけないのは歯がゆい。できればその辺の処理もロックオンシステムオブジェクトで処理させちゃいたい。

というより視野角に収まってる状態かどうかの判定なんていらないのかな・・・

それと、敵が一機だった場合のみのロジックになってるから複数の敵を考慮するロジックに修正する必要がある。武器の左右のロック速度が違った場合のロジックもいれないとね。

以上です。

弾でダメージを与える

動いて弾が撃てるようになったので、破壊可能なターゲットを設置して弾を当てることで破壊できるようにする。

ので以下の内容を実装する。
①武器オブジェクトから弾丸オブジェクトを生成する際に、武器オブジェクト内で保有するステータスを元に弾丸を生成する。
→これによって武器オブジェをいじることによって、撃ち出される弾丸を替えれる。
②ターゲットに弾丸オブジェクトと当たった際に、弾丸の威力を参照し、その分だけHPを減らす
③ターゲットのHPがなくなったら破壊

インスタンスでオブジェクトを生成する際に、GameObject型として代入しておく。
こやつをBullet型に置き換えれば・・・
Bulletオブジェクトで用意しておいた公開関数・変数を使用したり代入できます。

②③

当たり判定は OnCollisionEnterで取得
引数のCollision型をBulletオブジェクトに置き換えれば①同様に後はどうとでもなる。
簡単にオブジェクト型を変えれるGetComponet関数が最強に使いやすい。
他にもオブジェクト型を変える方法はあるんだろうけどとりあえずはこいつを使いまくってこうと思う。

あと変数の定義がテキトーすぎなのは(公開範囲とか)許してくだちー

そんなこんなでこう

HPの残量が分かるようにターゲットの色をだんだん変えるようにしました。

以上です。

動きをACっぽく

今回は以下の自機の挙動を改善・追加していくよ

1.通常移動方法の改善
2.クイックブーストの追加
3.飛行ブースト(上昇)の追加
4.摩擦の改善

1.通常移動方法の改善
今までの移動方法は、チュートリアルと同じようにRigidbody.AddForceによって、移動したい方向に力を加えていた。
この移動方法ではACっぽい動きを実現するのは難しい。

なので、現在速度ベクトルとの目標速度ベクトル差分から作速度差分ベクトルを作成することにした。
この速度差分ベクトルを現在の速度ベクトルに加算することで機体の移動を実現する。
また、速度差分ベクトルの大きさを変えることで機体ごとの加速度の違いを作れたりできるはず。
ここでいう目標速度ベクトルっていうのはプレイヤーからの入力から得られるこう動きたいっていう目標値。
図にするとこんな感じ

んで現在速度ベクトルがこんな感じに変わる。

最高速度と加速度は機体毎にカスタマイズで変わるようにしていきたい。

最高速度:高
加速度:低

最高速度:低
加速度:高

ちょっと加速度高のやつは動きがキモい

2.クイックブーストの追加
ナチュラルにクイックブーストを追加しました。

あの一瞬だけ早くなって敵の弾をかわすやつね
こちらは噴射力と、噴射時間を調整できるようにして個性をだせるようにしたい
あとクイックブーストのクールタイム時間は全向き共通にしてるけど
ACだと違う向き(縦→横よか)にクイックブーストするときはクールタイムなかった希ガス。この辺は要調整。

3.飛行ブースト(上昇)の追加
コイツ!飛ぶぞ!!

押してる間だけy軸の速度が上昇していく、もちろん上層速度の上限は設けている。
とはいえ、y軸の動きをどう取り入れるかは悩みどころ。
空中をビュンビュン飛び回れると地形関係なくなっちゃうからそれは味気ない。
ジャンプを取り入れるか、一度離陸してからの上昇ブースト使用時間に制限を設けるとか。とりあえずこの動きは仮の実装。

4.摩擦の改善
Rigidbodyの摩擦係数を調整。
これで自機が壁にぶつかったときに摩擦で旋回してしまう現象を防げる。

方法としてはPhysic Materialっていうのを作成して、そこで摩擦係数を設定。
あとはD&Dでcolliderにその情報を待たしてやればおk
詳しくは以下
https://openbook4.me/projects/172/sections/1002

以上です。