脚本环境准备
确保引用了如下命名空间
1 2 using UnityEditor; using UnityEngine.InputSystem;
确保继承 IInputInteraction接口,也可以继承IInputInteraction<>这就限定了该interaction的 Value值类型
请在类名前加上
1 2 3 #if UNITY_EDITOR [InitializeOnLoad] #endif
和一个静态方法
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Initialize()
{
InputSystem.RegisterInteraction<TapHoldInteraction>();
}
保证该交互可在界面上编辑以及游戏中保持效果
具体实现 要重写两个方法
void Process(ref InputInteractionContext context)
void Reset()
用于交互失败或完成后重置
示例 自定义一个MultiTapHoldInteraction,多点击后按住开启交互,松开退出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 using JetBrains.Annotations;using System.Collections;using System.Collections.Generic;using UnityEditor;using UnityEngine;using UnityEngine.InputSystem;using UnityEngine.InputSystem.Interactions;#if UNITY_EDITOR [InitializeOnLoad ] #endif public class TapHoldInteraction : IInputInteraction { private enum TapPhase { None, WaitingForNextRelease, WaitingForNextPress, Hold } [Tooltip("hold所需时长" ) ] public float holdTime;[Tooltip("The maximum time (in seconds) allowed to elapse between pressing and releasing a control for it to register as a Tap" ) ] public float duration;[Tooltip("The maximum delay (in seconds) allowed between each tap. If this time is exceeded, the multi-tap is canceled." ) ] public float pressSpacing;[Tooltip("How many taps need to be performed in succession. Two means double-tap, three means triple-tap, and so on." ) ] public int tapCount=2 ;public float pressPoint;private TapPhase m_CurrentPhase;private int m_CurrentTapCount;private double m_CurrentTapStartTime;private double m_LastTapReleaseTime;private float holdTimeOrDefault=> ((double )holdTime > 0.0 ) ? duration : InputSystem.settings.defaultHoldTime;private float tapTimeOrDefault => ((double )duration > 0.0 ) ? duration : InputSystem.settings.defaultTapTime;internal float tapDelayOrDefault => ((double )pressSpacing > 0.0 ) ? pressSpacing : InputSystem.settings.multiTapDelayTime;private float pressPointOrDefault => (pressPoint > 0f ) ? pressPoint : InputSystem.settings.defaultButtonPressPoint;private float releasePointOrDefault => pressPointOrDefault * InputSystem.settings.buttonReleaseThreshold;public void Process (ref InputInteractionContext context ){ if (context.timerHasExpired) { if (m_CurrentPhase!=TapPhase.Hold) { context.Canceled(); } else { context.PerformedAndStayPerformed(); } return ; } switch (m_CurrentPhase) { case TapPhase.None: if (context.ControlIsActuated(pressPointOrDefault)) { m_CurrentPhase = TapPhase.WaitingForNextRelease; m_CurrentTapStartTime = context.time; float num = tapTimeOrDefault; float num2 = tapDelayOrDefault; float num3 = holdTimeOrDefault; context.SetTimeout(num); } break ; case TapPhase.WaitingForNextRelease: if (context.ControlIsActuated(releasePointOrDefault)) { break ; } if (context.time - m_CurrentTapStartTime <= (double )tapTimeOrDefault) { m_CurrentTapCount++; m_CurrentPhase = TapPhase.WaitingForNextPress; m_LastTapReleaseTime = context.time; context.SetTimeout(tapDelayOrDefault); } else { context.Canceled(); } break ; case TapPhase.WaitingForNextPress: if (!context.ControlIsActuated(pressPointOrDefault)) { break ; } if (context.time - m_LastTapReleaseTime <= (double )tapDelayOrDefault) { m_CurrentTapStartTime = context.time; if (m_CurrentTapCount + 1 >= tapCount) { context.Started(); m_CurrentTapCount++; context.SetTimeout(holdTimeOrDefault); break ; } m_CurrentPhase = TapPhase.WaitingForNextRelease; context.SetTimeout(tapTimeOrDefault); } else { context.Canceled(); } break ; case TapPhase.Hold: break ; } switch (context.phase) { case InputActionPhase.Started: if (context.time - m_CurrentTapStartTime >= (double )holdTimeOrDefault) { context.PerformedAndStayPerformed(); } if (!context.ControlIsActuated()) { context.Canceled(); } break ; case InputActionPhase.Performed: if (!context.ControlIsActuated(pressPointOrDefault)) { context.Canceled(); } break ; } } public void Reset (){ m_CurrentPhase = TapPhase.None; m_CurrentTapCount = 0 ; m_CurrentTapStartTime = 0.0 ; m_LastTapReleaseTime = 0.0 ; } [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad) ] private static void Initialize (){ InputSystem.RegisterInteraction<TapHoldInteraction>(); }
}
注意点:
建议交互成功触发后再开启Peformed(),一是由于规范,二是当调用Peformed()后超时器将会被隐式移除。