Raspberlyのブログ

Raspberlyのブログ

Unityネタをメインとした技術系ブログです。にゃんこ大戦争や日常なども。そろそろブログタイトル決めたい

【Unityネタ】オープンワールドでよく見るインジケーターを作ってみる

この記事はUnity Advent Calendar 2021 13日目の記事です。

qiita.com

昨日は@xrdnkさんによる「Unidux でマルチシーン画面遷移制御を行う」でした。

明日は@tsubaki_t1さんによる「Unity 2021.2のSceneViewで色々な操作を行う新機能、Overlayについて」です。

 

 

今回はオープンワールドゲームでよく見るインジケーターをUnityで実装してみます。

f:id:Raspberly:20211213010215g:plain

f:id:Raspberly:20211213012611p:plain

 

 

 

インジケーターとは

インジケーターは以下のGIFで表示されている白いバーのことです。
これはMETAL GEAR SOLID Vのプレイ映像ですが、敵に怪しまれると白いバーが画面に表示されます
このバーはこちらを怪しんでいる敵の方向を知らせてくれる役割を持ちます。

f:id:Raspberly:20211212210452g:plain

これをUnityで作ってみます。

 

恐らくゲームによって呼び方は違いますが、METAL GEAR SOLID Vではインジケーターと呼称されているため、
本記事でもインジケーターで表記します。

mgstpp-app.konamionline.com

 

 

 

開発環境

Unity 2020.3.22f1

デモのキャラクターモデルはユニティちゃん*1を使用しています

raspberly.hateblo.jp

 

 

 

実際に作ってみる

UIの作成

まずはインジケーターのUIを作っていきます。

Canvasを作成し、Canvasの子に空のGameObjectを作成します。名前はIndicatorBaseにしておきます。

f:id:Raspberly:20211212222927p:plain

IndicatorBaseのAnchorはMiddleCenterに設定します。(最初からそうなってるはず)

f:id:Raspberly:20211212222854p:plain

 

次に、IndicatorBaseの子にImageを作成。

f:id:Raspberly:20211212224602p:plain

インジケーターとして表示するSpriteを適当に用意しImageに設定しておきます。
AnchorはMiddleCenterに設定します。

f:id:Raspberly:20211212230331p:plain

PosYなどを設定し上を向くように配置します。

f:id:Raspberly:20211212225246p:plain

 

プレイヤーとエネミーの作成

適当にCapsuleとCubeを作成します。
Capsuleをプレイヤーに、Cubeをエネミーとして扱います。

f:id:Raspberly:20211212231505p:plain

それぞれ名前も変えておきます。

 

 

コンポーネントの作成

以下の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コンポーネントをアタッチします。(プレイヤーじゃなくてもいいが)

 

コンポーネントは以下のように設定します。

f:id:Raspberly:20211213043452p:plain

IndicatorにはIndicatorBaseを紐づけます。
インジケーター自体ではなく、その親を回転させるためです。

 

実際に動かすと、エネミーの動きに合わせてインジケーターが回転するのがわかります。

f:id:Raspberly:20211213002603g:plain

 

 

 

ユニティちゃんを使ったシーンで試してみました。
インジケーターのデザインを変えたり、敵に見つかったときだけ表示したり、
複数表示に対応したりと色々楽しめそうですね!

f:id:Raspberly:20211213010215g:plain

敵キャラにはこちらのアセットを使っています。

raspberly.hateblo.jp

 

 

 

まとめ

オープンワールドゲームでよく見るインジケーターを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のようにプレイヤーキャラクターとカメラが別方向を向くゲームで、プレイヤーを基準にするとプレイヤーがクルクル回転するたびインジケーターも荒ぶります。そのため敵の角度はカメラを基準にしています。
ただこれだと、敵とプレイヤーが密着した時に正しい角度がとれないため今のバージョンに修正しました。

 

 

参考資料

スクリプト内の計算についてはこちらから

fanblogs.jp

t-stove-k.hatenablog.com

 

www.create-forever.games

 

Quaternion.LookRotationは調べて初めて知りました。
こんな便利なものがあったんですね。

 

 

 

 

過去のアドベントカレンダー記事

raspberly.hateblo.jp

 

raspberly.hateblo.jp

 

raspberly.hateblo.jp

 

 

 

他、間違っている箇所、わかりにくい所がありましたらコメントにお願いします。

*1:© Unity Technologies Japan/UCL

*2:三人称視点シューティングゲーム