UniRxでマウス操作を実装してみる
UniRxの勉強のためにマウス操作を実装してみた。
スワイプとか結構面倒なイメージがあったけど、意外と簡単に書けた気がする。
やったこと
・左右のシングルクリックでオブジェクトの色を変える
・左右の同時クリックでオブジェクトの色を元に戻す
・左右のマウスボタンホールドで、収縮を繰り返す
・左クリックのスワイプでオブジェクトを移動させる
動作イメージ
左クリックでオブジェクトを黄色くします。
左クリックのホールドで、縮小⇔復元を繰り返します。
右クリックでオブジェクトを水色っぽくします。
右クリックのホールドで、拡大⇔復元を繰り返します。
左クリックでスワイプすると、距離に応じてオブジェクトが移動します。
左右の同時クリックでオブジェクトを元の色に戻します。
ソースコード
On***はオブザーバパターンのObservableで、メッセージを発行する側を想定した実装です。
Do***はオブザーバパターンのObserverで、メッセージを購読して処理をする側を想定した実装です。
左右同時クリックと、シングルクリックの排他は今回実装していません。
using System; using UnityEngine; using UniRx; using UniRx.Triggers; using DG.Tweening; public class PlayerController : MonoBehaviour { private float bounceScale = 1.0f; // 収縮するときの大きさ private int sign = 1; // 拡大⇔縮小を反転させる符号 private float cameraScale = 5f / 540f; // カメラ領域とUnityの単位とを合わせるScale private Color leftClickColor = Color.yellow; // 左クリックしたときの色 private Color rightClickColor = Color.cyan; // 右クリックしたときの色 private Color originalColor = Color.white; // 同時クリックしたときの色(元の色) // Start is called before the first frame update void Start() { // 左クリック処理の登録 OnLeftMouseDownObservable().Subscribe(_ => DoLeftClick()).AddTo(this); // 右クリック処理の登録 OnRightMouseDownObservable().Subscribe(_ => DoRightClick()).AddTo(this); // 左右同時クリック処理の登録 Observable .Merge(OnLeftMouseDownObservable().Select(_ => KeyCode.Mouse0), OnRightMouseDownObservable().Select(_ => KeyCode.Mouse1)) .Buffer(timeSpan: TimeSpan.FromSeconds(0.1f)) // 100msの間クリックを受け付け .Where(x => x.Count == 2 && x[0] != x[1]) // 二回クリック、かつ左右クリック .Subscribe(_ => DoSimultaneousClick()) .AddTo(this); // 左マウスホールド処理の登録 OnLeftMouseHoldObservable().Subscribe(_ => DoLeftMouseHold()).AddTo(this); // 右マウスホールド処理の登録 OnRightMouseHoldObservable().Subscribe(_ => DoRightMouseHold()).AddTo(this); // スワイプ処理の登録 OnLeftMouseDownObservable().Select(_ => Input.mousePosition).Take(1) .Concat(OnLeftMouseUpObservable().Select(_ => Input.mousePosition).Take(1)) .Aggregate((pre, cur) => cur - pre) .RepeatUntilDestroy(this) .Subscribe(x => DoSwipe(x)) .AddTo(this); } /// <summary> /// 左クリック(押す)をイベント発行するObservable /// </summary> private IObservable<Unit> OnLeftMouseDownObservable() { return this.UpdateAsObservable().Where(_ => Input.GetMouseButtonDown(0)); } /// <summary> /// 左クリック(離す)をイベント発行するObservable /// </summary> private IObservable<Unit> OnLeftMouseUpObservable() { return this.UpdateAsObservable().Where(_ => Input.GetMouseButtonUp(0)); } /// <summary> /// 右クリックをイベント発行するObservable /// </summary> private IObservable<Unit> OnRightMouseDownObservable() { return this.UpdateAsObservable().Where(_ => Input.GetMouseButtonDown(1)); } /// <summary> /// マウス左ホールドイベントを発行するObservable /// </summary> private IObservable<Unit> OnLeftMouseHoldObservable() { return this.UpdateAsObservable().Where(_ => Input.GetMouseButton(0)); } /// <summary> /// マウス右ホールドイベントを発行するObservable /// </summary> private IObservable<Unit> OnRightMouseHoldObservable() { return this.UpdateAsObservable().Where(_ => Input.GetMouseButton(1)); } /// <summary> /// 左クリック処理 /// </summary> private void DoLeftClick() { GetComponent<SpriteRenderer>().color = leftClickColor; } /// <summary> /// 右クリック処理 /// </summary> private void DoRightClick() { GetComponent<SpriteRenderer>().color = rightClickColor; } /// <summary> /// 同時クリック /// </summary> private void DoSimultaneousClick() { GetComponent<SpriteRenderer>().color = originalColor; } private void DoLeftMouseHold() { if (bounceScale < 0.8f) sign = 1; else if (bounceScale >= 1.0f) sign = -1; bounceScale += Time.deltaTime * sign; bounceScale = bounceScale > 1.0f ? 1.0f : bounceScale; transform.localScale = Vector3.one * bounceScale; } private void DoRightMouseHold() { if (bounceScale <= 1.0f) sign = 1; else if (bounceScale > 1.2f) sign = -1; bounceScale += Time.deltaTime * sign; bounceScale = bounceScale < 1.0f ? 1.0f : bounceScale; transform.localScale = Vector3.one * bounceScale; } private void DoSwipe(Vector3 move) { transform.DOMove(move * cameraScale, 0.5f) .SetRelative(true) .SetEase(Ease.OutQuint); } }