123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- using UnityEngine;
- using UnityEngine.EventSystems;
- using UnityEngine.InputSystem;
- using UnityEngine.InputSystem.Controls;
- using UnityEngine.InputSystem.EnhancedTouch;
- using UnityEngine.InputSystem.Layouts;
- using UnityEngine.InputSystem.OnScreen;
- using UnityEngine.Serialization;
- [AddComponentMenu("Input/虚拟摇杆 - 新输入系统(InputSystem)")]
- public class JoyStick_InputSystem : OnScreenControl, IPointerDownHandler
- {
- enum JoyStickType
- {
- [InspectorName("固定在默认位置")]
- FixedInDefaultPosition = 0,
- [InspectorName("固定在触摸位置")]
- FixedInClickPosition = 1,
- [InspectorName("跟随触摸移动")]
- Flexible = 2
- }
- [Header("基础设置")]
- [Tooltip("摇杆背景")]
- [SerializeField]
- private RectTransform joyStickBackGround;
- [Tooltip("摇杆按钮")]
- [SerializeField]
- private RectTransform joyStickButton;
- [Tooltip("摇杆按钮移动范围(半径)")]
- [FormerlySerializedAs("movementRange")]
- [SerializeField]
- private float movementRange = 50;
- [Tooltip("控制设备路径")]
- [InputControl(layout = "Vector2")]
- [SerializeField]
- private new string controlPath;
- [Header("类型设置")]
- [Tooltip("摇杆类型")]
- [SerializeField]
- private JoyStickType joyStickType;
- [Tooltip("摇杆是否默认隐藏")]
- [SerializeField]
- private bool isHideWithoutTouch;
- //触摸屏(设备)
- private Touchscreen currentTouchScreen;
- //控制摇杆的触点对象
- private TouchControl joyStickTouch;
- //摇杆初始位置
- private Vector2 joyStickStartPos;
- //与屏幕相关的相机(主要用于将屏幕上的位置转换为某UI矩形内的相对位置)
- private Camera screenCamera;
- //模拟(鼠标或者笔)输入
- private TouchSimulation touchSimulation;
- //画布渲染模式
- private RenderMode renderMode;
- //点击区域UI的RectTransform
- private RectTransform rectTransform;
- protected override string controlPathInternal
- {
- get => controlPath;
- set => controlPath = value;
- }
- private void Awake()
- {
- #if UNITY_EDITOR
- if (!gameObject.TryGetComponent(out touchSimulation))
- {
- touchSimulation = gameObject.AddComponent<TouchSimulation>();
- }
- #endif
- }
- private void Start()
- {
- currentTouchScreen = Touchscreen.current;
- //记录摇杆初始位置
- joyStickStartPos = joyStickBackGround.anchoredPosition;
- if (isHideWithoutTouch)
- {
- joyStickBackGround.gameObject.SetActive(false);
- }
- //获取画布的渲染模式
- var canvas = transform.GetComponentInParent<Canvas>();
- renderMode = canvas != null ? canvas.renderMode : RenderMode.ScreenSpaceOverlay;
- //获取点击区域UI的RectTransform
- rectTransform = transform.GetComponent<RectTransform>();
- }
- private void Update()
- {
- UpdateJoyStickUIPos();
- }
- private void OnDestroy()
- {
- #if UNITY_EDITOR
- touchSimulation = null;
- #endif
- }
- public void OnPointerDown(PointerEventData eventData)
- {
- //获取与屏幕相关的相机
- if (renderMode != RenderMode.ScreenSpaceOverlay)
- {
- screenCamera = eventData.pressEventCamera;
- }
- //摇杆没有被控制时分配控制权
- if (joyStickTouch == null)
- {
- for (int i = 0; i < currentTouchScreen.touches.Count; i++)
- {
- var touch = currentTouchScreen.touches[i];
- if (touch.phase.ReadValue() == UnityEngine.InputSystem.TouchPhase.Began)
- {
- if (
- RectTransformUtility.RectangleContainsScreenPoint(
- rectTransform,
- touch.position.ReadValue(),
- screenCamera
- )
- )
- {
- joyStickTouch = touch;
- RectTransformUtility.ScreenPointToLocalPointInRectangle(
- rectTransform,
- joyStickTouch.position.ReadValue(),
- screenCamera,
- out var joyStickBgPos
- );
- SetJoyStickUI(joyStickBgPos, Vector2.zero, true);
- }
- }
- }
- }
- }
- private void UpdateJoyStickUIPos()
- {
- if (joyStickTouch == null)
- return;
- bool isActive = true;
- Vector2 joyStickBgPos = Vector2.zero;
- Vector2 joyStickBtnPos = Vector2.zero;
- Vector2 sendToControlValue = Vector2.zero;
- switch (joyStickTouch.phase.ReadValue())
- {
- case UnityEngine.InputSystem.TouchPhase.None:
- break;
- case UnityEngine.InputSystem.TouchPhase.Began:
- case UnityEngine.InputSystem.TouchPhase.Moved:
- //更新摇杆位置数据
- RectTransformUtility.ScreenPointToLocalPointInRectangle(
- rectTransform,
- joyStickTouch.position.ReadValue(),
- screenCamera,
- out var touchInRectPos
- );
- Vector2 delta = touchInRectPos - joyStickBackGround.anchoredPosition;
- joyStickBgPos = joyStickBackGround.anchoredPosition;
- if (joyStickType == JoyStickType.Flexible)
- {
- if (delta.magnitude > movementRange)
- {
- joyStickBgPos += delta.normalized * (delta.magnitude - movementRange);
- }
- }
- joyStickBtnPos = Vector2.ClampMagnitude(delta, movementRange);
- isActive = true;
- sendToControlValue = delta / movementRange;
- break;
- case UnityEngine.InputSystem.TouchPhase.Ended:
- case UnityEngine.InputSystem.TouchPhase.Canceled:
- //收回Touch对摇杆的控制权
- joyStickTouch = null;
- joyStickBgPos = joyStickStartPos;
- isActive = false;
- break;
- case UnityEngine.InputSystem.TouchPhase.Stationary:
- break;
- }
- //设置摇杆位置
- SetJoyStickUI(joyStickBgPos, joyStickBtnPos, isActive);
- //给控制器发送新位置
- SendValueToControl(sendToControlValue);
- }
- private void SetJoyStickUI(Vector2 joyStickBgPos, Vector2 joyStickBtnPos, bool isActive)
- {
- //设置joyStickBackGround位置
- switch (joyStickType)
- {
- case JoyStickType.FixedInDefaultPosition:
- break;
- case JoyStickType.FixedInClickPosition:
- case JoyStickType.Flexible:
- joyStickBackGround.anchoredPosition = joyStickBgPos;
- break;
- }
- //设置joyStickButton位置
- joyStickButton.anchoredPosition = joyStickBtnPos;
- //设置
- if (isHideWithoutTouch && joyStickBackGround.gameObject.activeSelf != isActive)
- {
- joyStickBackGround.gameObject.SetActive(isActive);
- }
- }
- }
|