using System; using System.Collections; using System.Threading; using Cysharp.Threading.Tasks; using Game; using Game.Pool; using UnityEngine; public enum TouchType { None, // 无状态输入 单击, // 超过0.3s未再次点击判定为单击 双击, // 第二次点击时间为0.3s内,判定为双击 长按, // 长按某个位置时间超过1.5s,判定为长按 放大, // 双指内掐 缩小, //双指外扩 由左向右滑动, 由右向左滑动, 由后向前滑动, 由前向后滑动, } public interface ITouchManager { TouchType TouchType { get; } } public class TouchManager : ManagerBase, ITouchManager { private TouchType oldType; private TouchType touchType; public TouchType TouchType => this.touchType; private float currentDoubleTime; private float currentLongTime; private float maxDoubleTime = 0.3f; private float maxLongTime = 1.5f; private bool isDoubleStarting; private bool isLongStarting; private float f = 5f; // events public Action OnClick; // 单击 public Action OnDoubleClick; // 双击 public Action OnLongClick; // 长按 public Action OnBlowUp; // 放大 public Action OnBlowDown; // 缩小 public Action OnLeftToRight; // 由左向右滑动 public Action OnRightToLeft; // 由右向左滑动 public Action OnFrontToBack; // 由前向后滑动 public Action OnBackToFront; // 由后向前滑动 private void Start() { this.isDoubleStarting = false; this.isLongStarting = false; } private void Update() { if (Input.touchCount == 1) { this.One(); } else if (Input.touchCount == 2) { this.IsEnlarge(); } } private string oldId; private string newId; private string currentId; void One() { Touch touch0 = Input.GetTouch(0); var vector2 = touch0.deltaPosition; switch (touch0.phase) { case TouchPhase.Began: this.newId = Guid.NewGuid().ToString(); this.currentId = this.newId; break; case TouchPhase.Moved: if (this.currentId != this.newId) { return; } if (vector2.x > f) ChangeState(TouchType.由左向右滑动); else if (vector2.x < -f) ChangeState(TouchType.由右向左滑动); if (vector2.y > f) ChangeState(TouchType.由前向后滑动); else if (vector2.y < -f) ChangeState(TouchType.由后向前滑动); break; case TouchPhase.Stationary: break; case TouchPhase.Ended: this.oldId = this.newId; ChangeState(TouchType.None); break; case TouchPhase.Canceled: break; default: throw new ArgumentOutOfRangeException(); } if (vector2 == Vector2.zero) // 使用实现 { if (touch0.phase == TouchPhase.Began && !this.isDoubleStarting) { this.isDoubleStarting = true; // if (this.Double != null) // StopCoroutine(this.Double); // Double = this.UpdateDouble(); // StartCoroutine(this.Double); if (this.doubleToken != null && !this.doubleToken.isDispose) { this.doubleToken.Cancel(); } this.doubleToken = TokenPool.GetToken(); this.Double = UpdateDouble(this.doubleToken); this.Double.Forget(); } if (touch0.phase == TouchPhase.Began && !this.isLongStarting) { this.isLongStarting = true; // if (this.Long != null) // StopCoroutine(this.Long); // Long = this.UpdateLong(); // StartCoroutine(this.Long); if (this.longToken != null && !this.longToken.isDispose) { this.longToken.Cancel(); } this.longToken = TokenPool.GetToken(); this.Long = UpdateLong(this.longToken); this.Long.Forget(); } } } // TODO: add private bool isFinish; private UniTask Double; private ITokenInfo doubleToken; private UniTask Long; private ITokenInfo longToken; async UniTask UpdateDouble(ITokenInfo tokenInfo) { if (this.isFinish) this.isFinish = false; string tmpId = this.currentId; this.currentDoubleTime = 0; while (this.currentDoubleTime < this.maxDoubleTime) { if (tokenInfo.isDispose) { return; } await UniTask.Yield(); this.currentDoubleTime += Time.deltaTime; if (Input.touchCount == 1 && tmpId != this.currentId && Input.GetTouch(0).phase == TouchPhase.Ended) { // 双击 ChangeState(TouchType.双击); this.isFinish = true; this.isDoubleStarting = false; tokenInfo.Dispose(); return; } if (this.isFinish) { this.isDoubleStarting = false; tokenInfo.Cancel(); return; } } if (tmpId == this.currentId) { if (!this.isFinish && Input.touchCount == 0) { ChangeState(TouchType.单击); this.isFinish = true; } } this.isDoubleStarting = false; tokenInfo.Dispose(); // 双击不成立 } async UniTask UpdateLong(ITokenInfo tokenInfo) { if (this.isFinish) this.isFinish = false; this.currentLongTime = 0; while (this.currentLongTime < this.maxLongTime) { await UniTask.Yield(); this.currentLongTime += Time.deltaTime; if (this.isFinish) { tokenInfo.Cancel(); return; } if (Input.touchCount == 0 || Input.GetTouch(0).phase != TouchPhase.Stationary) { this.touchType = TouchType.None; isLongStarting = false; tokenInfo.Dispose(); return; } } while (Input.GetTouch(0).phase == TouchPhase.Ended) { await UniTask.Yield(); } if (!this.isFinish) { ChangeState(TouchType.长按); this.isLongStarting = false; this.isFinish = true; } tokenInfo.Dispose(); } private Vector2 old1; private Vector2 old2; void IsEnlarge() { Touch touch0 = Input.GetTouch(0); Touch touch1 = Input.GetTouch(1); Vector2 new1 = touch0.position; Vector2 new2 = touch1.position; float length1 = Mathf.Sqrt((old1.x - old2.x) * (old1.x - old2.x) + (old1.y - old2.y) * (old1.y - old2.y)); float length2 = Mathf.Sqrt((new1.x - new2.x) * (new1.x - new2.x) + (new1.y - new2.y) * (new1.y - new2.y)); if (length1 < length2) ChangeState(TouchType.放大); else if (length1 > length2) ChangeState(TouchType.缩小); else ChangeState(TouchType.None); this.old1 = new1; this.old2 = new2; } private void ChangeState(TouchType newType) { this.oldType = this.touchType; this.touchType = newType; FireEvent(newType); } void FireEvent(TouchType newType) { switch (newType) { case TouchType.None: break; case TouchType.单击: this.OnClick?.Invoke(); break; case TouchType.双击: this.OnDoubleClick?.Invoke(); break; case TouchType.长按: this.OnLongClick?.Invoke(); break; case TouchType.放大: this.OnBlowUp?.Invoke(); break; case TouchType.缩小: this.OnBlowDown?.Invoke(); break; case TouchType.由左向右滑动: this.OnLeftToRight?.Invoke(); break; case TouchType.由右向左滑动: this.OnRightToLeft?.Invoke(); break; case TouchType.由后向前滑动: this.OnBackToFront?.Invoke(); break; case TouchType.由前向后滑动: this.OnFrontToBack?.Invoke(); break; default: throw new ArgumentOutOfRangeException(nameof(newType), newType, null); } } }