shaoxiadiablo/Assets/AGame/Scripts/Platform/WechatTouchInputOverride.cs
2025-05-18 01:04:31 +08:00

182 lines
4.2 KiB
C#

#if SDK_WECHAT_WASM
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using WeChatWASM;
using Touch = UnityEngine.Touch;
class TouchData
{
public Touch touch;
public long timeStamp;
}
/**
* 由于Unity WebGL发布的多点触控存在问题, 导致在微信中多点触控存在粘连的情况
* 所以需要使用WX的触控接口重新覆盖Unity的BaseInput关于触控方面的接口
* 通过设置StandaloneInputModule.inputOverride的方式来实现
*/
[RequireComponent(typeof(StandaloneInputModule))]
public class WechatTouchInputOverride : BaseInput
{
private bool _isInitWechatSDK;
private readonly List<TouchData> _touches = new List<TouchData>();
private StandaloneInputModule _standaloneInputModule = null;
protected override void Awake()
{
base.Awake();
_standaloneInputModule = GetComponent<StandaloneInputModule>();
}
protected override void OnEnable()
{
base.OnEnable();
InitWechatTouchEvents();
if (_standaloneInputModule)
{
_standaloneInputModule.inputOverride = this;
}
}
protected override void OnDisable()
{
base.OnDisable();
UnregisterWechatTouchEvents();
if (_standaloneInputModule)
{
_standaloneInputModule.inputOverride = null;
}
}
private void InitWechatTouchEvents()
{
if (!_isInitWechatSDK)
{
WX.InitSDK((code) =>
{
_isInitWechatSDK = true;
Debug.LogFormat("WX.InitSDK:{0}", code);
RegisterWechatTouchEvents();
});
}
else
{
RegisterWechatTouchEvents();
}
}
private void RegisterWechatTouchEvents()
{
WX.OnTouchStart(OnWxTouchStart);
WX.OnTouchMove(OnWxTouchMove);
WX.OnTouchEnd(OnWxTouchEnd);
}
private void UnregisterWechatTouchEvents()
{
WX.OffTouchStart(OnWxTouchStart);
WX.OffTouchMove(OnWxTouchMove);
WX.OffTouchEnd(OnWxTouchEnd);
}
private void OnWxTouchStart(OnTouchStartCallbackResult touchEvent)
{
foreach (var wxTouch in touchEvent.changedTouches)
{
var data = FindOrCreateTouchData(wxTouch.identifier);
data.touch.phase = TouchPhase.Began;
data.touch.position = new Vector2(wxTouch.clientX, wxTouch.clientY);
data.touch.rawPosition = data.touch.position;
data.timeStamp = touchEvent.timeStamp;
// Debug.Log($"OnWxTouchStart:{wxTouch.identifier}, {data.touch.phase}");
}
}
private void OnWxTouchMove(OnTouchStartCallbackResult touchEvent)
{
foreach (var wxTouch in touchEvent.changedTouches)
{
var data = FindOrCreateTouchData(wxTouch.identifier);
UpdateTouchData(data, new Vector2(wxTouch.clientX, wxTouch.clientY), touchEvent.timeStamp, TouchPhase.Moved);
}
}
private void OnWxTouchEnd(OnTouchStartCallbackResult touchEvent)
{
foreach (var wxTouch in touchEvent.changedTouches)
{
var data = FindOrCreateTouchData(wxTouch.identifier);
UpdateTouchData(data, new Vector2(wxTouch.clientX, wxTouch.clientY), touchEvent.timeStamp, TouchPhase.Ended);
}
}
private void Update()
{
RemoveEndedTouches();
}
private void RemoveEndedTouches()
{
if (_touches.Count > 0)
{
_touches.RemoveAll(touchData =>
{
var touch = touchData.touch;
return (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled);
});
}
}
private TouchData FindOrCreateTouchData(long identifier)
{
foreach (var touchData in _touches)
{
var touch = touchData.touch;
if (touch.fingerId == identifier)
{
return touchData;
}
}
var data = new TouchData();
data.touch.pressure = 1.0f;
data.touch.maximumPossiblePressure = 1.0f;
data.touch.type = TouchType.Direct;
data.touch.tapCount = 1;
data.touch.fingerId = (int)identifier;
data.touch.radius = 0;
data.touch.radiusVariance = 0;
data.touch.altitudeAngle = 0;
data.touch.azimuthAngle = 0;
data.touch.deltaTime = 0;
_touches.Add(data);
return data;
}
private static void UpdateTouchData(TouchData data, Vector2 pos, long timeStamp, TouchPhase phase)
{
data.touch.phase = phase;
data.touch.deltaPosition = pos - data.touch.position;
data.touch.position = pos;
data.touch.deltaTime = (timeStamp - data.timeStamp) / 1000000.0f;
}
public override bool touchSupported
{
get
{
return true;
}
}
public override int touchCount
{
get { return _touches.Count; }
}
public override Touch GetTouch(int index)
{
return _touches[index].touch;
}
}
#endif