InputSettings.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. using UnityEngine.InputSystem.Layouts;
  2. using UnityEngine.InputSystem.LowLevel;
  3. using UnityEngine.InputSystem.Processors;
  4. using UnityEngine.InputSystem.Utilities;
  5. ////TODO: make sure that alterations made to InputSystem.settings in play mode do not leak out into edit mode or the asset
  6. ////TODO: handle case of supportFixedUpdates and supportDynamicUpdates both being set to false; should it be an enum?
  7. ////TODO: figure out how this gets into a build
  8. ////TODO: allow setting up single- and multi-user configs for the project
  9. ////TODO: allow enabling/disabling plugins
  10. ////REVIEW: should the project settings include a list of action assets to use? (or to force into a build)
  11. ////REVIEW: add extra option to enable late-updates?
  12. ////REVIEW: put default sensor sampling frequency here?
  13. ////REVIEW: put default gamepad polling frequency here?
  14. namespace UnityEngine.InputSystem
  15. {
  16. /// <summary>
  17. /// Project-wide input settings.
  18. /// </summary>
  19. /// <remarks>
  20. /// Several aspects of the input system can be customized to tailor how the system functions to the
  21. /// specific needs of a project. These settings are collected in this class. There is one global
  22. /// settings object active at any one time. It can be accessed and set through <see cref="InputSystem.settings"/>.
  23. ///
  24. /// Changing a setting on the object takes effect immediately. It also triggers the
  25. /// <see cref="InputSystem.onSettingsChange"/> callback.
  26. /// </remarks>
  27. /// <seealso cref="InputSystem.settings"/>
  28. /// <seealso cref="InputSystem.onSettingsChange"/>
  29. public class InputSettings : ScriptableObject
  30. {
  31. /// <summary>
  32. /// Determine how the input system updates, i.e. processes pending input events.
  33. /// </summary>
  34. /// <value>When to run input updates.</value>
  35. /// <remarks>
  36. /// By default, input updates will automatically be triggered as part of the player loop.
  37. /// If <c>updateMode</c> is set to <see cref="UpdateMode.ProcessEventsInDynamicUpdate"/>
  38. /// (the default), then right at the beginning of a dynamic update (i.e. before all
  39. /// <c>MonoBehaviour.Update</c> methods are called), input is processed. And if <c>updateMode</c>
  40. /// is set to <see cref="UpdateMode.ProcessEventsInFixedUpdate"/>, then right at the beginning
  41. /// of each fixed update (i.e. before all <c>MonoBehaviour.FixedUpdate</c> methods are
  42. /// called), input is processed.
  43. ///
  44. /// Additionally, if there are devices that need updates right before rendering (see <see
  45. /// cref="InputDevice.updateBeforeRender"/>), an extra update will be run right before
  46. /// rendering. This special update will only consume input on devices that have
  47. /// <see cref="InputDevice.updateBeforeRender"/> set to <c>true</c>.
  48. ///
  49. /// You can run updates manually using <see cref="InputSystem.Update"/>. Doing so
  50. /// outside of tests is only recommended, however, if <c>updateMode</c> is set to
  51. /// <see cref="UpdateMode.ProcessEventsManually"/> (in which case it is actually required
  52. /// for input to be processed at all).
  53. ///
  54. /// Note that in the editor, input updates will also run before each editor update
  55. /// (i.e. as part of <c>EditorApplication.update</c>). Player and editor input state
  56. /// are kept separate, though, so any input consumed in editor updates will not be visible
  57. /// in player updates and vice versa.
  58. /// </remarks>
  59. /// <seealso cref="InputSystem.Update"/>
  60. public UpdateMode updateMode
  61. {
  62. get => m_UpdateMode;
  63. set
  64. {
  65. if (m_UpdateMode == value)
  66. return;
  67. m_UpdateMode = value;
  68. OnChange();
  69. }
  70. }
  71. /// <summary>
  72. /// If true, sensors that deliver rotation values on handheld devices will automatically adjust
  73. /// rotations when the screen orientation changes.
  74. /// </summary>
  75. /// <remarks>
  76. /// This is enabled by default.
  77. ///
  78. /// If enabled, rotation values will be rotated around Z. In <see cref="ScreenOrientation.Portrait"/>, values
  79. /// remain unchanged. In <see cref="ScreenOrientation.PortraitUpsideDown"/>, they will be rotated by 180 degrees.
  80. /// In <see cref="ScreenOrientation.LandscapeLeft"/> by 90 degrees, and in <see cref="ScreenOrientation.LandscapeRight"/>
  81. /// by 270 degrees.
  82. ///
  83. /// Sensors affected by this setting are <see cref="Accelerometer"/>, <see cref="Compass"/>, and <see cref="Gyroscope"/>.
  84. /// </remarks>
  85. /// <seealso cref="CompensateDirectionProcessor"/>
  86. public bool compensateForScreenOrientation
  87. {
  88. get => m_CompensateForScreenOrientation;
  89. set
  90. {
  91. if (m_CompensateForScreenOrientation == value)
  92. return;
  93. m_CompensateForScreenOrientation = value;
  94. OnChange();
  95. }
  96. }
  97. /// <summary>
  98. /// Whether to not make a device <c>.current</c> (see <see cref="InputDevice.MakeCurrent"/>)
  99. /// when there is only noise in the input.
  100. /// </summary>
  101. /// <value>Whether to check input on devices for noise.</value>
  102. /// <remarks>
  103. /// This is <em>disabled by default</em>.
  104. ///
  105. /// When toggled on, this property adds extra processing every time input is
  106. /// received on a device that is considered noisy. These devices are those that
  107. /// have at least one control that is marked as <see cref="InputControl.noisy"/>.
  108. /// A good example is the PS4 controller which has a gyroscope sensor built into
  109. /// the device. Whereas sticks and buttons on the device require user interaction
  110. /// to produce non-default values, the gyro will produce varying values even if
  111. /// the device just sits there without user interaction.
  112. ///
  113. /// Without noise filtering, a PS4 controller will thus continually make itself
  114. /// current as it will send a continuous stream of input even when not actively
  115. /// used by the player. By toggling this property on, each input event will be
  116. /// run through a noise mask. Only if state has changed outside of memory areas
  117. /// marked as noise will the input be considered valid user interaction and the
  118. /// device will be made current. Note that in this process, the system does
  119. /// <em>not</em> determine whether non-noisy controls on the device have actually
  120. /// changed value. All the system establishes is whether such controls have changed
  121. /// <em>state</em>. However, processing such as for deadzones may cause values
  122. /// to not effectively change even though the non-noisy state of the device has
  123. /// changed.
  124. /// </remarks>
  125. /// <seealso cref="InputDevice.MakeCurrent"/>
  126. /// <seealso cref="InputControl.noisy"/>
  127. public bool filterNoiseOnCurrent
  128. {
  129. get => m_FilterNoiseOnCurrent;
  130. set
  131. {
  132. if (m_FilterNoiseOnCurrent == value)
  133. return;
  134. m_FilterNoiseOnCurrent = value;
  135. OnChange();
  136. }
  137. }
  138. /// <summary>
  139. /// Default value used when nothing is set explicitly on <see cref="StickDeadzoneProcessor.min"/>
  140. /// or <see cref="AxisDeadzoneProcessor.min"/>.
  141. /// </summary>
  142. /// <value>Default lower limit for deadzones.</value>
  143. /// <remarks>
  144. /// "Deadzones" refer to limits established for the range of values accepted as input
  145. /// on a control. If the value for the control falls outside the range, i.e. below the
  146. /// given minimum or above the given maximum, the value is clamped to the respective
  147. /// limit.
  148. ///
  149. /// This property configures the default lower bound of the value range.
  150. ///
  151. /// Note that deadzones will by default re-normalize values after clamping. This means that
  152. /// inputs at the lower and upper end are dropped and that the range in-between is re-normalized
  153. /// to [0..1].
  154. ///
  155. /// Note that deadzones preserve the sign of inputs. This means that both the upper and
  156. /// the lower deadzone bound extend to both the positive and the negative range. For example,
  157. /// a deadzone min of 0.1 will clamp values between -0.1 and +0.1.
  158. ///
  159. /// The most common example of where deadzones are used are the sticks on gamepads, i.e.
  160. /// <see cref="Gamepad.leftStick"/> and <see cref="Gamepad.rightStick"/>. Sticks will
  161. /// usually be wobbly to some extent (just how wobbly varies greatly between different
  162. /// types of controllers -- which means that often deadzones need to be configured on a
  163. /// per-device type basis). Using deadzones, stick motion at the extreme ends of the spectrum
  164. /// can be filtered out and noise in these areas can effectively be eliminated this way.
  165. ///
  166. /// The default value for this property is 0.125.
  167. /// </remarks>
  168. /// <seealso cref="StickDeadzoneProcessor"/>
  169. /// <seealso cref="AxisDeadzoneProcessor"/>
  170. public float defaultDeadzoneMin
  171. {
  172. get => m_DefaultDeadzoneMin;
  173. set
  174. {
  175. if (m_DefaultDeadzoneMin == value)
  176. return;
  177. m_DefaultDeadzoneMin = value;
  178. OnChange();
  179. }
  180. }
  181. /// <summary>
  182. /// Default value used when nothing is set explicitly on <see cref="StickDeadzoneProcessor.max"/>
  183. /// or <see cref="AxisDeadzoneProcessor.max"/>.
  184. /// </summary>
  185. /// <value>Default upper limit for deadzones.</value>
  186. /// <remarks>
  187. /// "Deadzones" refer to limits established for the range of values accepted as input
  188. /// on a control. If the value for the control falls outside the range, i.e. below the
  189. /// given minimum or above the given maximum, the value is clamped to the respective
  190. /// limit.
  191. ///
  192. /// This property configures the default upper bound of the value range.
  193. ///
  194. /// Note that deadzones will by default re-normalize values after clamping. This means that
  195. /// inputs at the lower and upper end are dropped and that the range in-between is re-normalized
  196. /// to [0..1].
  197. ///
  198. /// Note that deadzones preserve the sign of inputs. This means that both the upper and
  199. /// the lower deadzone bound extend to both the positive and the negative range. For example,
  200. /// a deadzone max of 0.95 will clamp values of &gt;0.95 and &lt;-0.95.
  201. ///
  202. /// The most common example of where deadzones are used are the sticks on gamepads, i.e.
  203. /// <see cref="Gamepad.leftStick"/> and <see cref="Gamepad.rightStick"/>. Sticks will
  204. /// usually be wobbly to some extent (just how wobbly varies greatly between different
  205. /// types of controllers -- which means that often deadzones need to be configured on a
  206. /// per-device type basis). Using deadzones, stick motion at the extreme ends of the spectrum
  207. /// can be filtered out and noise in these areas can effectively be eliminated this way.
  208. ///
  209. /// The default value for this property is 0.925.
  210. /// </remarks>
  211. /// <seealso cref="StickDeadzoneProcessor"/>
  212. /// <seealso cref="AxisDeadzoneProcessor"/>
  213. public float defaultDeadzoneMax
  214. {
  215. get => m_DefaultDeadzoneMax;
  216. set
  217. {
  218. if (m_DefaultDeadzoneMax == value)
  219. return;
  220. m_DefaultDeadzoneMax = value;
  221. OnChange();
  222. }
  223. }
  224. /// <summary>
  225. /// The default value threshold for when a button is considered pressed. Used if
  226. /// no explicit thresholds are set on parameters such as <see cref="Controls.ButtonControl.pressPoint"/>
  227. /// or <see cref="Interactions.PressInteraction.pressPoint"/>.
  228. /// </summary>
  229. /// <value>Default button press threshold.</value>
  230. /// <remarks>
  231. /// In the input system, each button constitutes a full floating-point value. Pure
  232. /// toggle buttons, such as <see cref="Gamepad.buttonSouth"/> for example, will simply
  233. /// alternate between 0 (not pressed) and 1 (pressed). However, buttons may also have
  234. /// ranges, such as <see cref="Gamepad.leftTrigger"/> for example. When used in a context
  235. /// where a clear distinction between pressed and not pressed is required, we need a value
  236. /// beyond which we consider the button pressed.
  237. ///
  238. /// By setting this property, the default value for this can be configured. If a button
  239. /// has a value equal to or greater than the button press point, it is considered pressed.
  240. ///
  241. /// The default value is 0.5.
  242. ///
  243. /// Lowering the button press point will make triggers feel more like hair-triggers (akin
  244. /// to using the hair-trigger feature on Xbox Elite controllers). However, it may make using
  245. /// the directional buttons (i.e. <see cref="Controls.StickControl.up"/> etc) be fickle as
  246. /// solely moving in only one direction with sticks isn't easy. To counteract that, the button
  247. /// press points on the stick buttons can be raised.
  248. ///
  249. /// Another solution is to simply lower the press points on the triggers specifically.
  250. ///
  251. /// <example>
  252. /// <code>
  253. /// InputSystem.RegisterLayoutOverride(@"
  254. /// {
  255. /// ""name"" : ""HairTriggers"",
  256. /// ""extend"" : ""Gamepad"",
  257. /// ""controls"" [
  258. /// { ""name"" : ""leftTrigger"", ""parameters"" : ""pressPoint=0.1"" },
  259. /// { ""name"" : ""rightTrigger"", ""parameters"" : ""pressPoint=0.1"" }
  260. /// ]
  261. /// }
  262. /// ");
  263. /// </code>
  264. /// </example>
  265. /// </remarks>
  266. /// <seealso cref="Controls.ButtonControl.pressPoint"/>
  267. /// <seealso cref="Controls.ButtonControl.isPressed"/>
  268. /// <seealso cref="Interactions.PressInteraction.pressPoint"/>
  269. /// <seealso cref="Interactions.TapInteraction.pressPoint"/>
  270. /// <seealso cref="Interactions.SlowTapInteraction.pressPoint"/>
  271. /// <seealso cref="InputBindingCompositeContext.ReadValueAsButton"/>
  272. public float defaultButtonPressPoint
  273. {
  274. get => m_DefaultButtonPressPoint;
  275. set
  276. {
  277. if (m_DefaultButtonPressPoint == value)
  278. return;
  279. m_DefaultButtonPressPoint = value;
  280. OnChange();
  281. }
  282. }
  283. /// <summary>
  284. /// Default time (in seconds) within which a press and release has to occur for it
  285. /// to be registered as a "tap".
  286. /// </summary>
  287. /// <value>Default upper limit on press durations for them to register as taps.</value>
  288. /// <remarks>
  289. /// A tap is considered as a quick press-and-release on a button-like input control.
  290. /// This property determines just how quick the press-and-release has to be, i.e. what
  291. /// the maximum time is that can elapse between the button being pressed and released
  292. /// again. If the delay between press and release is greater than this time, the
  293. /// input does not qualify as a tap.
  294. ///
  295. /// The default tap time is 0.2 seconds.
  296. /// </remarks>
  297. /// <seealso cref="TapInteraction"/>
  298. public float defaultTapTime
  299. {
  300. get => m_DefaultTapTime;
  301. set
  302. {
  303. if (m_DefaultTapTime == value)
  304. return;
  305. m_DefaultTapTime = value;
  306. OnChange();
  307. }
  308. }
  309. public float defaultSlowTapTime
  310. {
  311. get => m_DefaultSlowTapTime;
  312. set
  313. {
  314. if (m_DefaultSlowTapTime == value)
  315. return;
  316. m_DefaultSlowTapTime = value;
  317. OnChange();
  318. }
  319. }
  320. public float defaultHoldTime
  321. {
  322. get => m_DefaultHoldTime;
  323. set
  324. {
  325. if (m_DefaultHoldTime == value)
  326. return;
  327. m_DefaultHoldTime = value;
  328. OnChange();
  329. }
  330. }
  331. public float tapRadius
  332. {
  333. get => m_TapRadius;
  334. set
  335. {
  336. if (m_TapRadius == value)
  337. return;
  338. m_TapRadius = value;
  339. OnChange();
  340. }
  341. }
  342. public float multiTapDelayTime
  343. {
  344. get => m_MultiTapDelayTime;
  345. set
  346. {
  347. if (m_MultiTapDelayTime == value)
  348. return;
  349. m_MultiTapDelayTime = value;
  350. OnChange();
  351. }
  352. }
  353. /// <summary>
  354. /// List of device layouts used by the project.
  355. /// </summary>
  356. /// <remarks>
  357. /// This would usually be one of the high-level abstract device layouts. For example, for
  358. /// a game that supports touch, gamepad, and keyboard&amp;mouse, the list would be
  359. /// <c>{ "Touchscreen", "Gamepad", "Mouse", "Keyboard" }</c>. However, nothing prevents the
  360. /// the user from adding something a lot more specific. A game that can only be played
  361. /// with a DualShock controller could make this list just be <c>{ "DualShockGamepad" }</c>,
  362. /// for example.
  363. ///
  364. /// In the editor, we use the information to filter what we display to the user by automatically
  365. /// filtering out irrelevant controls in the control picker and such.
  366. ///
  367. /// The information is also used when a new device is discovered. If the device is not listed
  368. /// as supported by the project, it is ignored.
  369. ///
  370. /// The list is empty by default. An empty list indicates that no restrictions are placed on what
  371. /// devices are supported. In this editor, this means that all possible devices and controls are
  372. /// shown.
  373. /// </remarks>
  374. /// <seealso cref="InputControlLayout"/>
  375. public ReadOnlyArray<string> supportedDevices
  376. {
  377. get => new ReadOnlyArray<string>(m_SupportedDevices);
  378. set
  379. {
  380. // Detect if there was a change.
  381. if (supportedDevices.Count == value.Count)
  382. {
  383. var hasChanged = false;
  384. for (var i = 0; i < supportedDevices.Count; ++i)
  385. if (m_SupportedDevices[i] != value[i])
  386. {
  387. hasChanged = true;
  388. break;
  389. }
  390. if (!hasChanged)
  391. return;
  392. }
  393. m_SupportedDevices = value.ToArray();
  394. OnChange();
  395. }
  396. }
  397. [Tooltip("Determine which type of devices are used by the application. By default, this is empty meaning that all devices recognized "
  398. + "by Unity will be used. Restricting the set of supported devices will make only those devices appear in the input system.")]
  399. [SerializeField] private string[] m_SupportedDevices;
  400. [Tooltip("Determine when Unity processes events. By default, accumulated input events are flushed out before each fixed update and "
  401. + "before each dynamic update. This setting can be used to restrict event processing to only where the application needs it.")]
  402. [SerializeField] private UpdateMode m_UpdateMode = UpdateMode.ProcessEventsInDynamicUpdate;
  403. [SerializeField] private bool m_CompensateForScreenOrientation = true;
  404. [SerializeField] private bool m_FilterNoiseOnCurrent = false;
  405. [SerializeField] private float m_DefaultDeadzoneMin = 0.125f;
  406. [SerializeField] private float m_DefaultDeadzoneMax = 0.925f;
  407. // A setting of 0.5 seems to roughly be what games generally use on the gamepad triggers.
  408. // Having a higher value here also obsoletes the need for custom press points on stick buttons
  409. // (the up/down/left/right ones).
  410. [SerializeField] private float m_DefaultButtonPressPoint = 0.5f;
  411. [SerializeField] private float m_DefaultTapTime = 0.2f;
  412. [SerializeField] private float m_DefaultSlowTapTime = 0.5f;
  413. [SerializeField] private float m_DefaultHoldTime = 0.4f;
  414. [SerializeField] private float m_TapRadius = 5;
  415. [SerializeField] private float m_MultiTapDelayTime = 0.75f;
  416. internal void OnChange()
  417. {
  418. if (InputSystem.settings == this)
  419. InputSystem.s_Manager.ApplySettings();
  420. }
  421. internal const int s_OldUnsupportedFixedAndDynamicUpdateSetting = 0;
  422. /// <summary>
  423. /// How the input system should update.
  424. /// </summary>
  425. /// <remarks>
  426. /// By default, the input system will run event processing as part of the player loop. In the default configuration,
  427. /// the processing will happens once before every every dynamic update (<see cref="Update"/>), i.e. <see cref="ProcessEventsInDynamicUpdate"/>
  428. /// is the default behavior.
  429. ///
  430. /// There are two types of updates not governed by UpdateMode. One is <see cref="InputUpdateType.Editor"/> which
  431. /// will always be enabled in the editor and govern input updates for <see cref="UnityEditor.EditorWindow"/>s in
  432. /// sync to <see cref="UnityEditor.EditorApplication.update"/>.
  433. ///
  434. /// The other update type is <see cref="InputUpdateType.BeforeRender"/>. This type of update is enabled and disabled
  435. /// automatically in response to whether devices are present requiring this type of update (<see
  436. /// cref="InputDevice.updateBeforeRender"/>). This update does not consume extra state.
  437. /// </remarks>
  438. /// <seealso cref="InputSystem.Update"/>
  439. /// <seealso cref="InputUpdateType"/>
  440. /// <seealso cref="MonoBehaviour.FixedUpdate"/>
  441. /// <seealso cref="MonoBehaviour.Update"/>
  442. public enum UpdateMode
  443. {
  444. // Removed: ProcessEventsInBothFixedAndDynamicUpdate=0
  445. /// <summary>
  446. /// Automatically run input updates right before every <see cref="MonoBehaviour.Update"/>.
  447. /// </summary>
  448. /// <remarks>
  449. /// In this mode, no processing happens specifically for fixed updates. Querying input state in
  450. /// <see cref="MonoBehaviour.FixedUpdate"/> will result in errors being logged in the editor and in
  451. /// development builds. In release player builds, the value of the dynamic update state is returned.
  452. /// </remarks>
  453. ProcessEventsInDynamicUpdate = 1,
  454. /// <summary>
  455. /// Automatically input run updates right before every <see cref="MonoBehaviour.FixedUpdate"/>.
  456. /// </summary>
  457. /// <remarks>
  458. /// In this mode, no processing happens specifically for dynamic updates. Querying input state in
  459. /// <see cref="MonoBehaviour.Update"/> will result in errors being logged in the editor and in
  460. /// development builds. In release player builds, the value of the fixed update state is returned.
  461. /// </remarks>
  462. ProcessEventsInFixedUpdate,
  463. /// <summary>
  464. /// Do not run updates automatically. In this mode, <see cref="InputSystem.Update"/> must be called
  465. /// manually to update input.
  466. /// </summary>
  467. /// <remarks>
  468. /// This mode is most useful for placing input updates in the frame explicitly at an exact location.
  469. ///
  470. /// Note that failing to call <see cref="InputSystem.Update"/> may result in a lot of events
  471. /// accumulating or some input getting lost.
  472. /// </remarks>
  473. ProcessEventsManually,
  474. }
  475. }
  476. }