Unityには、RectangleContainsScreenPointというマイナーな便利メソッドがある。
これを使うと、スマホゲームに必須の「移動ボタンが押しっ放しか」の判定が出来る。
UIの前後や、アクティブ状態等が考慮されない仕様なので、Canvas.enabledでフラグ管理。
細かい注意点は、コード内のコメントに残しています。
2021/10/10:大幅修正。
サンプル動画
適当に移動を導入した物。
テストコード
実行すると、「押下・押している最中・押上」のタイミングでコンソールに表示が出る。
//使わなかった為、一応コメントアウトしている。
//using System.Collections;
//using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Test : MonoBehaviour
{
//インスペクターから、対象のボタンを紐付けしておく。
[SerializeField]
RectTransform buttonRt;
//インスペクターから、対象のボタンの親キャンバスを紐付けしておく。
//プレイヤーが移動不可能な時はenabledを無効化しておく(メニュー画面を開いた時等)。
[SerializeField]
Canvas buttonCanvas;
void Update()
{
//ボタンの親キャンバスが無効化されている場合は、タッチ判定しないように弾く。
//(GameObject.activeSelfで判定すると、親オブジェクトを非アクティブ化した場合に望んだ動作をしない為、こちらに変更)
if (!buttonCanvas.enabled)
return;
if (Input.GetMouseButtonDown(0)) {
if (RectTransformUtility.RectangleContainsScreenPoint(buttonRt, Input.mousePosition)) {
OnDown();
}
} else if (Input.GetMouseButton(0)) {
if (RectTransformUtility.RectangleContainsScreenPoint(buttonRt, Input.mousePosition)) {
OnPressed();
}
} else if (Input.GetMouseButtonUp(0)) {
if (RectTransformUtility.RectangleContainsScreenPoint(buttonRt, Input.mousePosition)) {
OnRelease();
}
}
}
//押下した瞬間。
void OnDown()
{
print("OnDown");
}
//押している最中(ポインターが、ボタンの上の状態)。
//ここでプレイヤーの移動用メソッドを呼ぶ。
void OnPressed()
{
print("OnPressed");
}
//押上した瞬間(ポインターが、ボタンの上で放した場合のみ)。
void OnRelease()
{
print("OnRelease");
}
}
コード
以下があると仮定したコード。
- Playerというクラスが存在。
- Playerに移動用のメソッド「MoveLeft」、「MoveRight」が作成済み。
//使わなかった為、一応コメントアウトしている。
//using System.Collections;
//using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UIManager : MonoBehaviour
{
//インスペクターから、左移動のボタンを紐付けしておく。
[SerializeField]
RectTransform moveLeftButtonRt;
//インスペクターから、右移動のボタンを紐付けしておく。
[SerializeField]
RectTransform moveRightButtonRt;
//インスペクターから、対象のボタンの親キャンバスを紐付けしておく。
//プレイヤーが移動不可能な時はenabledを無効化しておく(メニュー画面を開いた時等)。
[SerializeField]
Canvas buttonCanvas;
//インスペクターから、プレイヤーを紐付けしておく。
[SerializeField]
Player player;
Vector3 touchPosition;
void Update()
{
//ボタンの親キャンバスが無効化されている場合は、タッチ判定しないように弾く。
//(GameObject.activeSelfで判定すると、親オブジェクトを非アクティブ化した場合には期待する動作をしない為、こちらに変更)
if (!buttonCanvas.enabled)
return;
if (Input.GetMouseButton(0)) {
touchPosition = Input.mousePosition;
if (RectTransformUtility.RectangleContainsScreenPoint(moveLeftButtonRt, touchPosition)) {
player.MoveLeft();
} else if (RectTransformUtility.RectangleContainsScreenPoint(moveRightButtonRt, touchPosition)) {
player.MoveRight();
}
}
}
}