bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

入力

入力周りは得意じゃないので練習。
スワイプ開始時のタッチがタップ判定になってしまう。
https://dl.dropbox.com/u/67579260/Unity/Test02/WebPlayer/WebPlayer.html


テスト環境

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class InputTest : MonoBehaviour {
	
	int [] inputFlag;
	
	
	void Awake() {
		inputFlag = new int [4];
		for(int i = 0; i < 4; ++i) {
			inputFlag[i] = 0;
		}
	}
	
	void Start() {
	}
	
	void Update() {
		Vector3 pos = Vector3.zero;
		float param = 0.0f;
		if(InputManager.Instance.Tap(ref pos)) {
			inputFlag[0] = 60;
		}
		if(InputManager.Instance.TapAndHold(ref pos, ref param)) {
			inputFlag[1] = 60;
		}
		if(InputManager.Instance.Swipe(ref pos)) {
			inputFlag[2] = 60;
		}
		if(InputManager.Instance.Pinch(ref pos, ref param)) {
			inputFlag[3] = 60;
		}
	}
	
	void OnGUI() {
		if(inputFlag[0] > 0) {
			GUILayout.Label("Tap");
			inputFlag[0]--;
		}
		if(inputFlag[1] > 0) {
			GUILayout.Label("TapAndHold");
			inputFlag[1]--;
		}
		if(inputFlag[2] > 0) {
			GUILayout.Label("Swipe");
			inputFlag[2]--;
		}
		if(inputFlag[3] > 0) {
			GUILayout.Label("Pinch");
			inputFlag[3]--;
		}
	}
}

入力管理クラス

using UnityEngine;
using System.Collections;

/*
 * @brief	入力管理.
 * @note	PC専用.
 * 			ピンチはマウスのホイール.
 */
public class InputManager : MonoBehaviour {
	
	/* シングルトンインスタンス. */
	private static InputManager instance = null;
	public static InputManager Instance {
		get { return instance; }
	}
	
	/* インスペクタ設定. */
	public bool DEBUG_LOG = false;
	public float PINCH_JUDGE = 0.001f;
	public float SWIPE_JUDGE = 10.0f;
	public float HOLD_JUDGE = 1.0f;
	
	/* 入力状態. */
	enum eState {
		None		=0,
		Any			=1<<31,
		Tap			=Any|1<<0,
		TapAndHold	=Any|1<<1,
		Swipe		=Any|1<<2,
		Pinch		=Any|1<<3,
	};
	
	/* 入力状態. */
	eState state = eState.None;
	/* マウスの開始点. */
	Vector3 startPosition = Vector3.zero;
	/* マウスの現在点. */
	Vector3 currentPosition = Vector3.zero;
	/* 開始時間. */
	float startTime = 0.0f;
	/* 現在の時間. */
	float currentTime = 0.0f;
	/* ピンチ中心点. */
	Vector3 pinchCenter = Vector3.zero;
	/* ピンチ距離. */
	float pinchDistance = 0.0f;
	
	/*
	 * @brief	タップ状態取得.
	 */
	public bool Tap(ref Vector3 tapPos) {
		bool ret = state == eState.Tap;
		if(ret) {
			tapPos = startPosition;
		}
		return ret;
	}
	
	/*
	 * @brief	タップアンドホールド状態取得.
	 */
	public bool TapAndHold(ref Vector3 tapPos, ref float time) {
		bool ret = state == eState.TapAndHold;
		if(ret) {
			tapPos = startPosition;
			time = currentTime-startTime;
		}
		return ret;
	}
	
	/*
	 * @brief	スワイプ状態取得.
	 */
	public bool Swipe(ref Vector3 swipeDir) {
		bool ret = state == eState.Swipe;
		if(ret) {
			swipeDir = currentPosition-startPosition;
		}
		return ret;
	}
	
	/*
	 * @brief	ピンチ状態取得.
	 * @note	distが負ならピンチアウト.
	 * 			distが正ならピンチイン.
	 */
	public bool Pinch(ref Vector3 centerPos, ref float dist) {
		bool ret = state == eState.Pinch;
		if(ret) {
			centerPos = pinchCenter;
			dist = pinchDistance;
		}
		return ret;
	}
	
	/*
	 * @brief	生成時処理.
	 */
	void Awake() {
		if(instance == null) {
			instance = this;
			DontDestroyOnLoad(gameObject);
		} else {
			Destroy(gameObject);
		}
	}

	/*
	 * @brief	更新前に一度.
	 */
	void Start () {
		state = eState.None;
	}
	
	/*
	 * @brief	更新.
	 */
	void Update () {
		UpdateInput();
	}
	
	/*
	 * @brief	GUI
	 */
	void OnGUI() {
		if(!DEBUG_LOG) {
			return;
		}
		
		if(state == eState.Tap) {
			GUILayout.Label("Tap:"+startPosition);
		}
		if(state == eState.TapAndHold) {
			GUILayout.Label("TapAndHold:"+startPosition+","+(currentTime-startTime));
		}
		if(state == eState.Swipe) {
			GUILayout.Label("Swipe:"+startPosition+","+currentPosition);
		}
		if(state == eState.Pinch) {
			GUILayout.Label("Pinch:"+pinchDistance);
		}
	}
	
	/*
	 * @brief	入力判定.
	 */
	void UpdateInput() {
		
		pinchDistance = Input.GetAxis("Mouse ScrollWheel");
		if(Input.GetMouseButtonDown(0)) {
			startTime = currentTime = Time.time;
			startPosition = currentPosition = Input.mousePosition;
			state = eState.Any;
		}
		else if(Input.GetMouseButton(0)) {
			currentTime = Time.time;
			currentPosition = Input.mousePosition;
		}
		else if(Input.GetMouseButtonUp(0)) {
			currentTime = Time.time;
			currentPosition = Input.mousePosition;
		}
		else if(Mathf.Abs(pinchDistance) > PINCH_JUDGE) {
			state = eState.Pinch;
			pinchCenter = Input.mousePosition;
		}
		else {
			state = eState.None;
		}
		
		if((state & eState.Any)!=0) {
			CheckState();
		}
	}
	
	/*
	 * @brief	入力状態決定.
	 */
	void CheckState() {
		if(state == eState.Pinch) {
			return;
		}
		
		float diff_distance = Vector3.Distance(currentPosition, startPosition);
		float diff_time = currentTime - startTime;
		
		if(CheckTap(diff_distance, diff_time)) {
			state = eState.Tap;
		}
		else if(CheckTapAndHold(diff_distance, diff_time)) {
			state = eState.TapAndHold;
		}
		else if(CheckSwipe(diff_distance, diff_time)) {
			state = eState.Swipe;
		}
	}
	
	/*
	 * @brief	タップ.
	 */
	bool CheckTap(float dist, float time) {
		bool ret = false;
		if(dist < SWIPE_JUDGE && time < HOLD_JUDGE) {
			ret = true;
		}
		return ret;
	}
	
	/*
	 * @brief	タップアンドホールド.
	 */
	bool CheckTapAndHold(float dist, float time) {
		bool ret = false;
		if(dist < SWIPE_JUDGE && time >= HOLD_JUDGE) {
			ret = true;
		}
		return ret;
	}
	
	/*
	 * @brief	スワイプ.
	 */
	bool CheckSwipe(float dist, float time) {
		bool ret = false;
		if(dist >= SWIPE_JUDGE) {
			ret = true;
		}
		return ret;
	}
}