PR

【Unity】モバイル向けバーチャルスティックを導入してみよう!

バーチャルスティック作ってみよう Unity

今回はUnityで使えるバーチャルスティックの作り方をお伝えしたいと思います。
私も最初作る方法がわからず悩んだ経験があるので同じような方の参考になれば幸いです。

 

はじめに

今回はバーチャルスティックを紹介したいと思います。
バーチャルスティックとはこんな感じのものです!

バーチャルスティック例

タッチするとスティックが現れてスライドすると入力が取得できるものです。

ゲームアプリでよく見るものですね!

 

 

導入方法

では作り方を説明したいと思います。
まずは下記のファイルをインポートしてください。

ダウンロード

ダウンロードはこちら
[Unity]バーチャルスティック

 

インポートする

ダウンロードが完了したらzipを解凍してunitypackageをご自身のプロジェクトに取り込んでください。

unitypackageのインポート方法がわからない方はこちらをご確認ください

Unityプラグイン(unitypackage)のインストール方法
今回はダウンロードしたUnityプラグイン(unitypackageファイル)を インストールする際に必要な手順を紹介したいと思います。

 

 

インポートされたフォルダ

まずインポートするとAssetsフォルダ以下に
下記のような「TedLab_VirtualStick」フォルダが追加されます。

 

インポート後フォルダ

 

こんな感じなら完璧です!

 

 

 

バーチャルスティックのPrefab

バーチャルスティックは下記のPrefabをシーンのCanvas以下に配置すれば利用できるようになります。

インポートしたフォルダのPrefab

Assets/TedLab_VirtualStick/Prefab/VirtualStick

これをご自身のシーンに置けば動くはず

 

 

バーチャルスティックをシーンに置いてみる

下記のようにシーンのCanvas以下にPrefabをドラッグ&ドロップして配置します。

CanvasはScreenSpaceにする

これで動くか実行して試してみてください

 

 

 

注意:Canvas設定を確認

ちなみにCanvasの設定は「ScreenSpace – Overlay」でなければ動作しないのでご注意ください。

CanvasはScreenSpaceにする

 

 

 

バーチャルスティックをカスタマイズする

基本的にPrefabの中身を変更していただければ下記を変更することが可能です。

 

タッチ反応範囲・移動範囲を設定

Prefabを開いてください。

VirtualStickオブジェクトを選択し、下記画像の箇所で

  1. タッチが反応する範囲を変更
  2. バーチャルスティックの幅を変更

が可能です。

タッチ・移動範囲をカスタマイズ

範囲を変更すれば右下だけ反応する

スティックの幅を広げれば操作感などを調整することができます!

 

 

バーチャルスティックのデザインを変更する

次はVirtualStickBack, VirtualStickBarwを変更することでデザインを変更することも可能です。

主に

  1. スティックのサイズ
  2. スティックのデザイン画像の差し替え
  3. スティックの色

などが下記で変更可能です。

スティックをカスタマイズ

ちなみにVirtualStickBarも同じ箇所で調整可能なので試してみてくださいね。

 

これでオリジナルのバーチャルスティックが作れるぞー!

 

 

 

ゲーム部分への反映

ただこれだとバーチャルスティックの挙動が行われるだけでゲーム側に値を受け取ることができません。

反映する場合は

VirtualStickGUIスクリプトを参照し、InputValueを参照してください。
すると現在どのような値になっているか0~1の値でx,yの値で取得することができます!

 

ちなみにSetStickEnableを呼び出すと

スティックのON/OFFが切り替えることができますよ!

 

 

 

スクリプト内容

こちらにスクリプトも貼っておきたいと思います。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;

namespace TedLab
{
    public class VirtualStickGUI : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler
    {
        public bool IsOperating{ get{ return m_operating; } }
        public Vector2 InputValue{ get{ return m_InputValue; } }

        [SerializeField] RectTransform refRectTransform = null;
        [SerializeField] Image joyStickBack = null;
        [SerializeField] Image joyStick = null;
        [SerializeField] float radius = 100f;
    
        Vector2 m_InputValue = Vector2.zero;
        Vector2 m_StartPosition = Vector2.zero;
        bool m_enable = true;
        bool m_operating = false;

	    void Start ()
        {
            joyStickBack.gameObject.SetActive(false);
            joyStick.gameObject.SetActive(false);
	    }

        public void OnPointerDown(PointerEventData data)
        {
            if(!m_enable){
                return;
            }
            m_operating = true;
            Vector2 pos = GetLocalPosition(data.position);
            joyStickBack.rectTransform.localPosition = pos;
            joyStick.rectTransform.localPosition = pos;
            m_StartPosition = pos;

            joyStickBack.gameObject.SetActive(true);
            joyStick.gameObject.SetActive(true);

            m_InputValue = Vector2.zero;
        }

        public void OnPointerUp(PointerEventData data)
        {
            if(!m_enable){
                return;
            }
            m_operating = false;
            joyStickBack.gameObject.SetActive(false);
            joyStick.gameObject.SetActive(false);

            m_InputValue = Vector2.zero;
        }

        public void OnDrag(PointerEventData data)
        {
            if(!m_enable){
                return;
            }

            Vector2 pos = GetLocalPosition(data.position);
            Vector2 vec = pos - m_StartPosition;
            float rad = Mathf.Atan2(vec.y, vec.x) * Mathf.Rad2Deg;
            float dist = vec.magnitude;

            if (dist <= radius)
            {
                joyStick.rectTransform.localPosition = pos;
            }
            else
            {
                joyStick.rectTransform.localPosition = new Vector2(m_StartPosition.x + radius * Mathf.Cos(rad * Mathf.Deg2Rad), m_StartPosition.y + radius * Mathf.Sin(rad * Mathf.Deg2Rad));
            }

            // 入力値(0~1)
            float param = Mathf.Min(dist, radius) / radius;
            vec.Normalize();
            m_InputValue = vec * param;
        }

        Vector2 GetLocalPosition(Vector2 screenPosition)
        {
            Vector2 result = Vector2.zero;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(refRectTransform, screenPosition, null, out result);
            return result;
        }

        // 有効設定
        public void SetStickEnable(bool enable)
        {
            m_enable = enable;

            if(!m_enable)
            {
                joyStickBack.gameObject.SetActive(false);
                joyStick.gameObject.SetActive(false);
                m_InputValue = Vector2.zero;
            }
        }
    
    }
}

 

 

機能を利用したゲーム(PR)

下記のゲームではこのバーチャルスティックを利用して開発しました。
ご興味がありましたらぜひ見ていただけると幸いです。

 

「妖怪剣劇アクション 妖言 零之章」 公式サイト
ゲーム「Yougen - 妖怪剣劇アクション」の公式サイトです。

鳥フライト 公式サイト
ゲームアプリ「鳥フライト」の公式サイトです。

 

 

終わりに

いかがでしたでしょうか?

今回は以外と調べても見つからなかったバーチャルスティックの実装を紹介してみました。
同じようにバーチャルスティックの実装方法がわからず苦労されている方の参考になれば幸いです。

ではここまでお読みいただきありがとうございました。

コメント

  1. 匿名 より:

    この仮想スティックのアセットの利用規約を教えて頂けませんか?商用利用(アプリゲーム等)の可否や報告義務、クレジットへの記載義務等を知りたいです。自分で探してみましたが、すでにどこかに書かれていたらすいません。

    • Tadapy Tadapy より:

      サイトの利用規約はこちらとなります。
      https://tedenglish.site/user-policy/

      開発についてはライセンス不要で自由に利用していただいて問題ないのですが
      本サイトを経由せずにダウンロードできてしまう二次配布に該当する場合は制限させていただいております。

スポンサーリンク
タイトルとURLをコピーしました