質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.51%

Unityでバーチャルパッドをマルチタップ対応させたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 721

kanata_02

score 19

前提・実現したいこと

Unity2DでiOS向けに2D横スクロールアクションを製作しています。
バーチャルパッド操作によってプレイヤーを移動させながら、画面上のオブジェクト(ステージ上に存在していて、タップ&ドラッグで移動させることが出来るアイテム)にも触れるようにしたいです。
ですが現在、ドラッグなどの操作は受け付けるもののバーチャルパッドを操作しながらアイテムを移動させると、アイテムがパッドのタップ位置とアイテムをタップした位置の中間に表示されてしまいます。こちらをどうにかしたいです。
マルチタップについて調べてみて、Input.touchCountでタップしている指の数を調べて、その数の分for分で処理する、というのは分かったのですがそれをどう組み込めばいいかがわかりません…。OnPointerDownなどでタップを取っている部分を変更すれば問題は解決できるのでしょうか?

かなり未熟な質問で申し訳ないのですが、方針だけでもアドバイスいただけると幸いです。よろしくお願いします。

バーチャルパッドの実装についてはこちらのサイトを参考にさせていただいております。
http://kan-kikuchi.hatenablog.com/entry/uGUI_Joystick_1

該当のソースコード

//バーチャルパッドにアタッチしているスクリプト
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
using System.Collections.Generic;

public class Joystick : Graphic, IPointerDownHandler, IPointerUpHandler, IEndDragHandler, IDragHandler
{

    //実際に動くスティック部分
    [SerializeField]
    [Header("実際に動くスティック部分(自動設定)")]
    private GameObject _stick = null;
    private const string STICK_NAME = "Stick";

    //スティックが動く範囲の半径
    [SerializeField]
    [Header("スティックが動く範囲の半径")]
    private float _radius = 100;

    //指を離した時にスティックが中心に戻るか
    [SerializeField]
    [Header("指を離した時にスティックが中心に戻るか")]
    private bool _shouldResetPosition = true;

    //現在地(x,y共に値が-1~1の範囲になる)
    [SerializeField]
    [Header("現在地(自動更新)")]
    private Vector2 _position = Vector2.zero;
    public Vector2 Position { get { return _position; } }

    //スティックの位置(Setter)
    private Vector3 _stickPosition
    {
        set
        {
            _stick.transform.localPosition = value;
            _position = new Vector2(
              _stick.transform.localPosition.x / _radius,
              _stick.transform.localPosition.y / _radius
            );
        }
    }

    //=================================================================================
    //初期化
    //=================================================================================

    protected override void Awake()
    {
        base.Awake();
        Init();
    }

    //スクリプトがロードされた時やインスペクターの値が変更されたときに呼び出される(エディター上のみ)
    protected override void OnValidate()
    {
        base.OnValidate();
        Init();
    }

    //初期化
    private void Init()
    {
        //スティックを生成する必要があれば生成し、位置を中心に設定
        CreateStickIfneeded();
        _stickPosition = Vector3.zero;

        //スティックのImage取得(なければ追加)、タッチ判定を取られないようにraycastTargetをfalseに
        Image stickImage = _stick.GetComponent<Image>();
        if (stickImage == null)
        {
            stickImage = _stick.AddComponent<Image>();
        }
        stickImage.raycastTarget = false;

        //タッチ判定を受け取れるようにRaycastTargetをTrueに
        raycastTarget = true;

        //タッチ判定をとる範囲は表示されないように透明に
        color = new Color(0, 0, 0, 0);
    }

    //スティックを生成する必要があれば生成
    private void CreateStickIfneeded()
    {
        //スティックが設定されていれば終了
        if (_stick != null)
        {
            return;
        }

        //スティックが子にあるか検索、あれば取得し終了
        if (transform.FindChild(STICK_NAME) != null)
        {
            _stick = transform.FindChild(STICK_NAME).gameObject;
            return;
        }

        //スティック生成
        _stick = new GameObject(STICK_NAME);
        _stick.transform.SetParent(gameObject.transform);
        _stick.transform.localRotation = Quaternion.identity;
    }

    //=================================================================================
    //タップ
    //=================================================================================

    //タップ開始時
    public void OnPointerDown(PointerEventData eventData)
    {
        //タップした瞬間にドラッグを開始した事にする
        OnDrag(eventData);
    }

    //タップ終了時(ドラッグ終了時には呼ばれない)
    public void OnPointerUp(PointerEventData eventData)
    {
        //タップした終了した時にドラッグを終了した時と同じ処理をする
        OnEndDrag(eventData);
    }

    //=================================================================================
    //ドラッグ
    //=================================================================================

    //ドラッグ終了時
    public void OnEndDrag(PointerEventData eventData)
    {
        if (_shouldResetPosition)
        {
            //スティックを中心に戻す
            _stickPosition = Vector3.zero;
        }
    }

    //ドラッグ中
    public void OnDrag(PointerEventData eventData)
    {
        //タップ位置を画面内の座標に変換し、スティックを移動
        Vector2 screenPos = Vector2.zero;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(GetComponent<RectTransform>(),
          new Vector2(Input.mousePosition.x, Input.mousePosition.y),
          null,
          out screenPos
        );

        _stickPosition = screenPos;

        //移動場所が設定した半径を超えてる場合は制限内に抑える
        float currentRadius = Vector3.Distance(Vector3.zero, _stick.transform.localPosition);
        if (currentRadius > _radius)
        {

            //角度計算
            float radian = Mathf.Atan2(_stick.transform.localPosition.y, _stick.transform.localPosition.x);

            //円上にXとYを設定
            Vector3 limitedPosition = Vector3.zero;
            limitedPosition.x = _radius * Mathf.Cos(radian);
            limitedPosition.y = _radius * Mathf.Sin(radian);

            _stickPosition = limitedPosition;
        }

    }

    //=================================================================================
    //更新
    //=================================================================================

#if UNITY_EDITOR
  //Gizmoを表示する
  private void OnDrawGizmos() {
    //スティックが移動できる範囲をScene上に表示
    UnityEditor.Handles.color = Color.green;
    UnityEditor.Handles.DrawWireDisc(transform.position , transform.forward, _radius * 0.5f);
  }
#endif

}
//移動させたいアイテムにアタッチしているスクリプト
//現在はEventTriggerで判定を取っています
void Start()
    {
        rigidbody = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        //ドラッグしているときの加速度
        if (!drag)
        {
            velocity *= Mathf.Pow(Attenuation, 10.0f * Time.deltaTime);
            this.transform.position += velocity * Time.deltaTime;
        }
    }

    public void OnDrag()
    {
        rigidbody.gravityScale = 0.0f;
        Vector3 prePos = this.transform.position;
        drag = true;
        Vector3 TapPos = Input.mousePosition;
        TapPos.z = 10f;
        transform.position = Camera.main.ScreenToWorldPoint(TapPos);
        transform.parent = null;

        velocity = (this.transform.position - prePos) / Time.deltaTime;
    }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • sakura_hana

    2019/07/23 16:07

    前述の通り、移動可能オブジェクトの方でもIDragHandlerを使ってみてください。
    public void OnDrag(PointerEventData eventData){ }
    この引数のeventDataが自分をドラッグしているタッチの情報になると思うので、こいつの座標データを見ればいいんじゃないかなと思います。

    キャンセル

  • kanata_02

    2019/07/25 20:03

    ご指摘の通り記述したところ、上手くそれぞれ別の動作しました!
    前回に引き続き助かりました。ありがとうございました!

    キャンセル

  • sakura_hana

    2019/07/26 09:25

    解決して何よりです。自己回答して質問クローズをお願いします。

    キャンセル

回答 1

check解決した方法

0

sakura_hana様のご指摘の通り、アイテムでもIDragHandlerを使用し記述したところ上手く動作しました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.51%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる