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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

1344閲覧

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

kanata_02

総合スコア25

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2019/07/22 15:54

編集2019/07/23 05:47

前提・実現したいこと

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

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

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

該当のソースコード

C#

1//バーチャルパッドにアタッチしているスクリプト 2using UnityEngine; 3using UnityEngine.UI; 4using UnityEngine.EventSystems; 5using System.Collections; 6using System.Collections.Generic; 7 8public class Joystick : Graphic, IPointerDownHandler, IPointerUpHandler, IEndDragHandler, IDragHandler 9{ 10 11 //実際に動くスティック部分 12 [SerializeField] 13 [Header("実際に動くスティック部分(自動設定)")] 14 private GameObject _stick = null; 15 private const string STICK_NAME = "Stick"; 16 17 //スティックが動く範囲の半径 18 [SerializeField] 19 [Header("スティックが動く範囲の半径")] 20 private float _radius = 100; 21 22 //指を離した時にスティックが中心に戻るか 23 [SerializeField] 24 [Header("指を離した時にスティックが中心に戻るか")] 25 private bool _shouldResetPosition = true; 26 27 //現在地(x,y共に値が-1~1の範囲になる) 28 [SerializeField] 29 [Header("現在地(自動更新)")] 30 private Vector2 _position = Vector2.zero; 31 public Vector2 Position { get { return _position; } } 32 33 //スティックの位置(Setter) 34 private Vector3 _stickPosition 35 { 36 set 37 { 38 _stick.transform.localPosition = value; 39 _position = new Vector2( 40 _stick.transform.localPosition.x / _radius, 41 _stick.transform.localPosition.y / _radius 42 ); 43 } 44 } 45 46 //================================================================================= 47 //初期化 48 //================================================================================= 49 50 protected override void Awake() 51 { 52 base.Awake(); 53 Init(); 54 } 55 56 //スクリプトがロードされた時やインスペクターの値が変更されたときに呼び出される(エディター上のみ) 57 protected override void OnValidate() 58 { 59 base.OnValidate(); 60 Init(); 61 } 62 63 //初期化 64 private void Init() 65 { 66 //スティックを生成する必要があれば生成し、位置を中心に設定 67 CreateStickIfneeded(); 68 _stickPosition = Vector3.zero; 69 70 //スティックのImage取得(なければ追加)、タッチ判定を取られないようにraycastTargetをfalseに 71 Image stickImage = _stick.GetComponent<Image>(); 72 if (stickImage == null) 73 { 74 stickImage = _stick.AddComponent<Image>(); 75 } 76 stickImage.raycastTarget = false; 77 78 //タッチ判定を受け取れるようにRaycastTargetをTrueに 79 raycastTarget = true; 80 81 //タッチ判定をとる範囲は表示されないように透明に 82 color = new Color(0, 0, 0, 0); 83 } 84 85 //スティックを生成する必要があれば生成 86 private void CreateStickIfneeded() 87 { 88 //スティックが設定されていれば終了 89 if (_stick != null) 90 { 91 return; 92 } 93 94 //スティックが子にあるか検索、あれば取得し終了 95 if (transform.FindChild(STICK_NAME) != null) 96 { 97 _stick = transform.FindChild(STICK_NAME).gameObject; 98 return; 99 } 100 101 //スティック生成 102 _stick = new GameObject(STICK_NAME); 103 _stick.transform.SetParent(gameObject.transform); 104 _stick.transform.localRotation = Quaternion.identity; 105 } 106 107 //================================================================================= 108 //タップ 109 //================================================================================= 110 111 //タップ開始時 112 public void OnPointerDown(PointerEventData eventData) 113 { 114 //タップした瞬間にドラッグを開始した事にする 115 OnDrag(eventData); 116 } 117 118 //タップ終了時(ドラッグ終了時には呼ばれない) 119 public void OnPointerUp(PointerEventData eventData) 120 { 121 //タップした終了した時にドラッグを終了した時と同じ処理をする 122 OnEndDrag(eventData); 123 } 124 125 //================================================================================= 126 //ドラッグ 127 //================================================================================= 128 129 //ドラッグ終了時 130 public void OnEndDrag(PointerEventData eventData) 131 { 132 if (_shouldResetPosition) 133 { 134 //スティックを中心に戻す 135 _stickPosition = Vector3.zero; 136 } 137 } 138 139 //ドラッグ中 140 public void OnDrag(PointerEventData eventData) 141 { 142 //タップ位置を画面内の座標に変換し、スティックを移動 143 Vector2 screenPos = Vector2.zero; 144 RectTransformUtility.ScreenPointToLocalPointInRectangle(GetComponent<RectTransform>(), 145 new Vector2(Input.mousePosition.x, Input.mousePosition.y), 146 null, 147 out screenPos 148 ); 149 150 _stickPosition = screenPos; 151 152 //移動場所が設定した半径を超えてる場合は制限内に抑える 153 float currentRadius = Vector3.Distance(Vector3.zero, _stick.transform.localPosition); 154 if (currentRadius > _radius) 155 { 156 157 //角度計算 158 float radian = Mathf.Atan2(_stick.transform.localPosition.y, _stick.transform.localPosition.x); 159 160 //円上にXとYを設定 161 Vector3 limitedPosition = Vector3.zero; 162 limitedPosition.x = _radius * Mathf.Cos(radian); 163 limitedPosition.y = _radius * Mathf.Sin(radian); 164 165 _stickPosition = limitedPosition; 166 } 167 168 } 169 170 //================================================================================= 171 //更新 172 //================================================================================= 173 174#if UNITY_EDITOR 175 //Gizmoを表示する 176 private void OnDrawGizmos() { 177 //スティックが移動できる範囲をScene上に表示 178 UnityEditor.Handles.color = Color.green; 179 UnityEditor.Handles.DrawWireDisc(transform.position , transform.forward, _radius * 0.5f); 180 } 181#endif 182 183} 184

C#

1//移動させたいアイテムにアタッチしているスクリプト 2//現在はEventTriggerで判定を取っています 3void Start() 4 { 5 rigidbody = GetComponent<Rigidbody2D>(); 6 } 7 8 void Update() 9 { 10 //ドラッグしているときの加速度 11 if (!drag) 12 { 13 velocity *= Mathf.Pow(Attenuation, 10.0f * Time.deltaTime); 14 this.transform.position += velocity * Time.deltaTime; 15 } 16 } 17 18 public void OnDrag() 19 { 20 rigidbody.gravityScale = 0.0f; 21 Vector3 prePos = this.transform.position; 22 drag = true; 23 Vector3 TapPos = Input.mousePosition; 24 TapPos.z = 10f; 25 transform.position = Camera.main.ScreenToWorldPoint(TapPos); 26 transform.parent = null; 27 28 velocity = (this.transform.position - prePos) / Time.deltaTime; 29 }

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sakura_hana

2019/07/23 04:51

クリック系インターフェースは「自分自身にポインターが乗ったら」「自分自身がドラッグされたら」などという考え方をします。なのでタップしている指の数を調べて……とかは必要ありません。 ・ジョイスティック用の画像を配置→ドラッグ時の処理実装(ジョイスティック用のクラス) ・移動可能オブジェクトの画像を配置→ドラッグ時の処理実装(移動可能オブジェクト用のクラス) とすれば出来るんじゃないかなと思います(未検証ですが)。 なお、単にジョイスティックというと外付けコントローラー(のスティック)のことを指すケースが多いので、今回の場合はリンク先にもありますが「バーチャルパッド」と記載した方がいいかと思います。
kanata_02

2019/07/23 05:45

追記・修正の依頼ありがとうございます。 現在ドラッグ操作は一応できる状態なのですが、タブレット端末でプレイしバーチャルパッドとアイテムのドラッグを同時に行うと、アイテムが二つのタップした場所の中間に表示されてしまいます。説明が足りずに申し訳ありません。 また、質問文に現在の状況を記載し、ジョイスティック→バーチャルパッドに表記を変更しました。ご指摘ありがとうございます。
sakura_hana

2019/07/23 07:07

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

2019/07/25 11:03

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

2019/07/26 00:25

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

回答1

0

自己解決

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

投稿2019/07/30 06:31

kanata_02

総合スコア25

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問