この記事はUnity Advent Calendar 2021 13日目の記事です。
昨日は@xrdnkさんによる「Unidux でマルチシーン画面遷移制御を行う」でした。
明日は@tsubaki_t1さんによる「Unity 2021.2のSceneViewで色々な操作を行う新機能、Overlayについて」です。
今回はオープンワールドゲームでよく見るインジケーターをUnityで実装してみます。
インジケーターとは
インジケーターは以下のGIFで表示されている白いバーのことです。
これはMETAL GEAR SOLID Vのプレイ映像ですが、敵に怪しまれると白いバーが画面に表示されます。
このバーはこちらを怪しんでいる敵の方向を知らせてくれる役割を持ちます。
これをUnityで作ってみます。
恐らくゲームによって呼び方は違いますが、METAL GEAR SOLID Vではインジケーターと呼称されているため、
本記事でもインジケーターで表記します。
開発環境
Unity 2020.3.22f1
デモのキャラクターモデルはユニティちゃん*1を使用しています
実際に作ってみる
UIの作成
まずはインジケーターのUIを作っていきます。
Canvasを作成し、Canvasの子に空のGameObjectを作成します。名前はIndicatorBaseにしておきます。
IndicatorBaseのAnchorはMiddleCenterに設定します。(最初からそうなってるはず)
次に、IndicatorBaseの子にImageを作成。
インジケーターとして表示するSpriteを適当に用意しImageに設定しておきます。
AnchorはMiddleCenterに設定します。
PosYなどを設定し上を向くように配置します。
プレイヤーとエネミーの作成
適当にCapsuleとCubeを作成します。
Capsuleをプレイヤーに、Cubeをエネミーとして扱います。
それぞれ名前も変えておきます。
コンポーネントの作成
以下のScriptをコピーし、IndicatorBaseコンポーネントを作成します。
using UnityEngine; public class IndicatorBase : MonoBehaviour { [SerializeField] Transform Player; [SerializeField] Transform Camera; [SerializeField] Transform Enemy; [SerializeField] RectTransform Indicator; void Update() { var rot = Quaternion.LookRotation(Enemy.position - Player.position); var angle = (Camera.eulerAngles - rot.eulerAngles).y; Indicator.localEulerAngles = new Vector3(0, 0, angle); } }
コンポーネントのアタッチ
プレイヤーにIndicatorBaseコンポーネントをアタッチします。(プレイヤーじゃなくてもいいが)
コンポーネントは以下のように設定します。
IndicatorにはIndicatorBaseを紐づけます。
インジケーター自体ではなく、その親を回転させるためです。
実際に動かすと、エネミーの動きに合わせてインジケーターが回転するのがわかります。
ユニティちゃんを使ったシーンで試してみました。
インジケーターのデザインを変えたり、敵に見つかったときだけ表示したり、
複数表示に対応したりと色々楽しめそうですね!
敵キャラにはこちらのアセットを使っています。
まとめ
オープンワールドゲームでよく見るインジケーターをUnityで作ってみました
ただ、スクリプトについてはまだまだ改善に余地がありそう。
一人称ゲームでもそのまま動作しますが、トップダウンなどカメラの挙動が異なるゲームで使用する場合スクリプトの修正が必要にかも。
以上です。
旧バージョン
途中でスクリプトを変えました。古いのはこっち
using UnityEngine; public class IndicatorBase : MonoBehaviour { [SerializeField] Transform Player; [SerializeField] Transform Enemy; [SerializeField] RectTransform Indicator; void Update() { var rot = Quaternion.LookRotation(Enemy.position - Player.position); var angle = (Player.eulerAngles - rot.eulerAngles).y; Indicator.localEulerAngles = new Vector3(0, 0, angle); } }
PlayerにはMainCameraを紐づけます。
TPS*2のようにプレイヤーキャラクターとカメラが別方向を向くゲームで、プレイヤーを基準にするとプレイヤーがクルクル回転するたびインジケーターも荒ぶります。そのため敵の角度はカメラを基準にしています。
ただこれだと、敵とプレイヤーが密着した時に正しい角度がとれないため今のバージョンに修正しました。
参考資料
スクリプト内の計算についてはこちらから
Quaternion.LookRotationは調べて初めて知りました。
こんな便利なものがあったんですね。
過去のアドベントカレンダー記事
他、間違っている箇所、わかりにくい所がありましたらコメントにお願いします。
*1:© Unity Technologies Japan/UCL
*2:三人称視点シューティングゲーム