using System; using System.Collections.Generic; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.Layouts; using UnityEngine.InputSystem.LowLevel; using UnityEngine.InputSystem.Processors; using UnityEngine.InputSystem.Utilities; namespace UnityEngine.InputSystem { /// /// Project-wide input settings. /// /// /// Several aspects of the input system can be customized to tailor how the system functions to the /// specific needs of a project. These settings are collected in this class. There is one global /// settings object active at any one time. It can be accessed and set through . /// /// Changing a setting on the object takes effect immediately. It also triggers the /// callback. /// /// /// public partial class InputSettings : ScriptableObject { /// /// Allows you to control how the input system handles updates. In other words, how and when pending input events are processed. /// /// When to run input updates. /// /// By default, input updates will automatically be triggered as part of the player loop. /// If updateMode is set to /// (the default), then right at the beginning of a dynamic update (i.e. before all /// MonoBehaviour.Update methods are called), input is processed. And if updateMode /// is set to , then right at the beginning /// of each fixed update (i.e. before all MonoBehaviour.FixedUpdate methods are /// called), input is processed. /// /// Additionally, if there are devices that need updates right before rendering (see ), an extra update will be run right before /// rendering. This special update will only consume input on devices that have /// set to true. /// /// You can run updates manually using . Doing so /// outside of tests is only recommended, however, if updateMode is set to /// (in which case it is actually required /// for input to be processed at all). /// /// Note that in the editor, input updates will also run before each editor update /// (i.e. as part of EditorApplication.update). Player and editor input state /// are kept separate, though, so any input consumed in editor updates will not be visible /// in player updates and vice versa. /// /// public UpdateMode updateMode { get => m_UpdateMode; set { if (m_UpdateMode == value) return; m_UpdateMode = value; OnChange(); } } /// /// Controls how platform-specific input should be converted when returning delta values for scroll wheel input actions. /// /// The conversion behavior. /// /// By default, the range used for the delta is normalized to a range of -1 to 1, to be uniform across all platforms. /// The alternative is that the native platform's scroll wheel range is returned, which is -120 to 120 for windows, and /// -1 to 1 for most other platforms. You should leave this value as the default uniform range unless you need to support /// legacy code that relies on the native platform-specific values. /// public ScrollDeltaBehavior scrollDeltaBehavior { get => m_ScrollDeltaBehavior; set { if (m_ScrollDeltaBehavior == value) return; m_ScrollDeltaBehavior = value; OnChange(); } } /// /// If true, sensors that deliver rotation values on handheld devices will automatically adjust /// rotations when the screen orientation changes. /// /// /// This is enabled by default. /// /// If enabled, rotation values will be rotated around Z. In , values /// remain unchanged. In , they will be rotated by 180 degrees. /// In by 90 degrees, and in /// by 270 degrees. /// /// Sensors affected by this setting are , , and . /// /// public bool compensateForScreenOrientation { get => m_CompensateForScreenOrientation; set { if (m_CompensateForScreenOrientation == value) return; m_CompensateForScreenOrientation = value; OnChange(); } } /// /// Currently: Option is deprecated and has no influence on the system. Filtering on noise is always enabled. /// Previously: Whether to not make a device .current (see ) /// when there is only noise in the input. /// /// /// We add extra processing every time input is /// received on a device that is considered noisy. These devices are those that /// have at least one control that is marked as . /// A good example is the PS4 controller which has a gyroscope sensor built into /// the device. Whereas sticks and buttons on the device require user interaction /// to produce non-default values, the gyro will produce varying values even if /// the device just sits there without user interaction. /// /// Without noise filtering, a PS4 controller will thus continually make itself /// current as it will send a continuous stream of input even when not actively /// used by the player. By toggling this property on, each input event will be /// run through a noise mask. Only if state has changed outside of memory areas /// marked as noise will the input be considered valid user interaction and the /// device will be made current. Note that in this process, the system does /// not determine whether non-noisy controls on the device have actually /// changed value. All the system establishes is whether such controls have changed /// state. However, processing such as for deadzones may cause values /// to not effectively change even though the non-noisy state of the device has /// changed. /// /// /// [Obsolete("filterNoiseOnCurrent is deprecated, filtering of noise is always enabled now.", false)] public bool filterNoiseOnCurrent { get => false; set { /* no op */ } } /// /// Default value used when nothing is set explicitly on /// or . /// /// Default lower limit for deadzones. /// /// "Deadzones" refer to limits established for the range of values accepted as input /// on a control. If the value for the control falls outside the range, i.e. below the /// given minimum or above the given maximum, the value is clamped to the respective /// limit. /// /// This property configures the default lower bound of the value range. /// /// Note that deadzones will by default re-normalize values after clamping. This means that /// inputs at the lower and upper end are dropped and that the range in-between is re-normalized /// to [0..1]. /// /// Note that deadzones preserve the sign of inputs. This means that both the upper and /// the lower deadzone bound extend to both the positive and the negative range. For example, /// a deadzone min of 0.1 will clamp values between -0.1 and +0.1. /// /// The most common example of where deadzones are used are the sticks on gamepads, i.e. /// and . Sticks will /// usually be wobbly to some extent (just how wobbly varies greatly between different /// types of controllers -- which means that often deadzones need to be configured on a /// per-device type basis). Using deadzones, stick motion at the extreme ends of the spectrum /// can be filtered out and noise in these areas can effectively be eliminated this way. /// /// The default value for this property is 0.125. /// /// /// public float defaultDeadzoneMin { get => m_DefaultDeadzoneMin; set { // ReSharper disable once CompareOfFloatsByEqualityOperator if (m_DefaultDeadzoneMin == value) return; m_DefaultDeadzoneMin = value; OnChange(); } } /// /// Default value used when nothing is set explicitly on /// or . /// /// Default upper limit for deadzones. /// /// "Deadzones" refer to limits established for the range of values accepted as input /// on a control. If the value for the control falls outside the range, i.e. below the /// given minimum or above the given maximum, the value is clamped to the respective /// limit. /// /// This property configures the default upper bound of the value range. /// /// Note that deadzones will by default re-normalize values after clamping. This means that /// inputs at the lower and upper end are dropped and that the range in-between is re-normalized /// to [0..1]. /// /// Note that deadzones preserve the sign of inputs. This means that both the upper and /// the lower deadzone bound extend to both the positive and the negative range. For example, /// a deadzone max of 0.95 will clamp values of >0.95 and <-0.95. /// /// The most common example of where deadzones are used are the sticks on gamepads, i.e. /// and . Sticks will /// usually be wobbly to some extent (just how wobbly varies greatly between different /// types of controllers -- which means that often deadzones need to be configured on a /// per-device type basis). Using deadzones, stick motion at the extreme ends of the spectrum /// can be filtered out and noise in these areas can effectively be eliminated this way. /// /// The default value for this property is 0.925. /// /// /// public float defaultDeadzoneMax { get => m_DefaultDeadzoneMax; set { // ReSharper disable once CompareOfFloatsByEqualityOperator if (m_DefaultDeadzoneMax == value) return; m_DefaultDeadzoneMax = value; OnChange(); } } /// /// The default value threshold for when a button is considered pressed. Used if /// no explicit thresholds are set on parameters such as /// or . /// /// Default button press threshold. /// /// In the input system, each button constitutes a full floating-point value. Pure /// toggle buttons, such as for example, will simply /// alternate between 0 (not pressed) and 1 (pressed). However, buttons may also have /// ranges, such as for example. When used in a context /// where a clear distinction between pressed and not pressed is required, we need a value /// beyond which we consider the button pressed. /// /// By setting this property, the default value for this can be configured. If a button /// has a value equal to or greater than the button press point, it is considered pressed. /// /// The default value is 0.5. /// /// Any value will implicitly be clamped to 0.0001f as allowing a value of 0 would /// cause all buttons in their default state to already be pressed. /// /// Lowering the button press point will make triggers feel more like hair-triggers (akin /// to using the hair-trigger feature on Xbox Elite controllers). However, it may make using /// the directional buttons (i.e. etc) be fickle as /// solely moving in only one direction with sticks isn't easy. To counteract that, the button /// press points on the stick buttons can be raised. /// /// Another solution is to simply lower the press points on the triggers specifically. /// /// /// /// InputSystem.RegisterLayoutOverride(@" /// { /// ""name"" : ""HairTriggers"", /// ""extend"" : ""Gamepad"", /// ""controls"" [ /// { ""name"" : ""leftTrigger"", ""parameters"" : ""pressPoint=0.1"" }, /// { ""name"" : ""rightTrigger"", ""parameters"" : ""pressPoint=0.1"" } /// ] /// } /// "); /// /// /// /// /// /// /// /// /// /// public float defaultButtonPressPoint { get => m_DefaultButtonPressPoint; set { // ReSharper disable once CompareOfFloatsByEqualityOperator if (m_DefaultButtonPressPoint == value) return; m_DefaultButtonPressPoint = Mathf.Clamp(value, ButtonControl.kMinButtonPressPoint, float.MaxValue); OnChange(); } } /// /// The percentage of at which a button that was pressed /// is considered released again. /// /// /// This setting helps avoid flickering around the button press point by introducing something akin to a /// "dead zone" below . Once a button has been pressed to a magnitude /// of at least , it is considered pressed and keeps being considered pressed /// until its magnitude falls back to a value of or below percent of /// . /// /// This is a percentage rather than a fixed value so it allows computing release /// points even when the press point has been customized. If, for example, a /// sets a custom , the respective release point /// can still be computed from the percentage set here. /// public float buttonReleaseThreshold { get => m_ButtonReleaseThreshold; set { // ReSharper disable once CompareOfFloatsByEqualityOperator if (m_ButtonReleaseThreshold == value) return; m_ButtonReleaseThreshold = value; OnChange(); } } /// /// Default time (in seconds) within which a press and release has to occur for it /// to be registered as a "tap". /// /// Default upper limit on press durations for them to register as taps. /// /// A tap is considered as a quick press-and-release on a button-like input control. /// This property determines just how quick the press-and-release has to be, i.e. what /// the maximum time is that can elapse between the button being pressed and released /// again. If the delay between press and release is greater than this time, the /// input does not qualify as a tap. /// /// The default tap time is 0.2 seconds. /// /// public float defaultTapTime { get => m_DefaultTapTime; set { // ReSharper disable once CompareOfFloatsByEqualityOperator if (m_DefaultTapTime == value) return; m_DefaultTapTime = value; OnChange(); } } /// /// Allows you to specify the default minimum duration required of a press-and-release interaction to evaluate to a slow-tap-interaction. /// /// The default minimum duration that the button-like input control must remain in pressed state for the interaction to evaluate to a slow-tap-interaction. /// /// A slow-tap-interaction is considered as a press-and-release sequence on a button-like input control. /// This property determines the lower bound of the duration that must elapse between the button being pressed and released again. /// If the delay between press and release is less than this duration, the input does not qualify as a slow-tap-interaction. /// /// The default slow-tap time is 0.5 seconds. /// /// public float defaultSlowTapTime { get => m_DefaultSlowTapTime; set { // ReSharper disable once CompareOfFloatsByEqualityOperator if (m_DefaultSlowTapTime == value) return; m_DefaultSlowTapTime = value; OnChange(); } } /// /// Allows you to specify the default minimum duration required of a press-and-release interaction to evaluate to a hold-interaction. /// /// The default minimum duration that the button-like input control must remain in pressed state for the interaction to evaluate to a hold-interaction. /// /// A hold-interaction is considered as a press-and-release sequence on a button-like input control. /// This property determines the lower bound of the duration that must elapse between the button being pressed and released again. /// If the delay between press and release is less than this duration, the input does not qualify as a hold-interaction. /// /// The default hold time is 0.4 seconds. /// /// public float defaultHoldTime { get => m_DefaultHoldTime; set { // ReSharper disable once CompareOfFloatsByEqualityOperator if (m_DefaultHoldTime == value) return; m_DefaultHoldTime = value; OnChange(); } } /// /// Allows you to specify the default maximum radius that a touch contact may be moved from its origin to evaluate to a tap-interaction. /// /// The default maximum radius (in pixels) that a touch contact may be moved from its origin to evaluate to a tap-interaction. /// /// A tap-interaction or slow-tap-interaction is considered as a press-and-release sequence. /// If the associated touch contact is moved a distance equal or greater to the value of this setting, /// the input sequence do not qualify as a tap-interaction. /// /// The default tap-radius is 5 pixels. /// /// /// /// public float tapRadius { get => m_TapRadius; set { // ReSharper disable once CompareOfFloatsByEqualityOperator if (m_TapRadius == value) return; m_TapRadius = value; OnChange(); } } /// /// Allows you to specify the maximum duration that may pass between taps in order to evaluate to a multi-tap-interaction. /// /// The default maximum duration (in seconds) that may pass between taps in order to evaluate to a multi-tap-interaction. /// /// A multi-tap interaction is considered as multiple press-and-release sequences. /// This property defines the maximum duration that may pass between these press-and-release sequences. /// If consecutive taps (press-and-release sequences) occur with a inter-sequence duration exceeding /// this property, the interaction do not qualify as a multi-tap-interaction. /// /// The default multi-tap delay time is 0.75 seconds. /// /// public float multiTapDelayTime { get => m_MultiTapDelayTime; set { // ReSharper disable once CompareOfFloatsByEqualityOperator if (m_MultiTapDelayTime == value) return; m_MultiTapDelayTime = value; OnChange(); } } /// /// When Application.runInBackground is true, this property determines what happens when application focus changes /// (see Application.isFocused) changes and how we handle /// input while running the background. /// /// What to do with input while not having focus. Set to by default. /// /// If Application.runInBackground is false, the value of this property is ignored. In that case, nothing happens when /// focus is lost. However, when focus is regained, is called on all devices. /// /// Note that in the editor as well as in development standalone players, Application.runInBackground will effectively always be /// turned on. The editor keeps the player loop running regardless of Game View focus for as long as the editor is active and in play mode /// and development players will implicitly turn on the setting during the build process. /// /// /// /// /// public BackgroundBehavior backgroundBehavior { get => m_BackgroundBehavior; set { if (m_BackgroundBehavior == value) return; m_BackgroundBehavior = value; OnChange(); } } /// /// Determines how player focus is handled in the editor with respect to input. /// /// /// This setting only has an effect while in play mode (see Application.isPlaying). /// While not in play mode, all input is invariably routed to the editor. /// /// The editor generally treats Game View focus as equivalent to application focus (see Application.isFocused). /// In other words, as long as any Game View has focus, the player is considered to have input focus. As soon as focus is transferred to a non-Game View /// EditorWindow or the editor as a whole loses focus, the player is considered to have lost input focus. /// /// However, unlike in built players, the editor will keep running the player loop while in play mode regardless of whether a Game View is focused /// or not. This essentially equates to Application.runInBackground always /// being true in the editor. /// /// To accommodate this behavior, this setting determines where input is routed while the player loop is running with no Game View being focused. As such, /// it also dictates which input reaches the editor (if any) while the game is playing. /// /// public EditorInputBehaviorInPlayMode editorInputBehaviorInPlayMode { get => m_EditorInputBehaviorInPlayMode; set { if (m_EditorInputBehaviorInPlayMode == value) return; m_EditorInputBehaviorInPlayMode = value; OnChange(); } } /// /// Determines how the Inspector window displays fields. /// /// public InputActionPropertyDrawerMode inputActionPropertyDrawerMode { get => m_InputActionPropertyDrawerMode; set { if (m_InputActionPropertyDrawerMode == value) return; m_InputActionPropertyDrawerMode = value; OnChange(); } } /// /// Upper limit on the amount of bytes worth of s processed in a single /// . /// /// /// This setting establishes a bound on the amount of input event data processed in a single /// update and thus limits throughput allowed for input. This prevents long stalls from /// leading to long delays in input processing. /// /// When the limit is exceeded, all events remaining in the buffer are thrown away (the /// is reset) and an error is logged. After that, the current /// update will abort and early out. /// /// Setting this property to 0 or a negative value will disable the limit. /// /// The default value is 5MB. /// /// /// public int maxEventBytesPerUpdate { get => m_MaxEventBytesPerUpdate; set { if (m_MaxEventBytesPerUpdate == value) return; m_MaxEventBytesPerUpdate = value; OnChange(); } } /// /// Upper limit on the number of s that can be queued within one /// . /// /// This settings establishes an upper limit on the number of events that can be queued /// using during a single update. This prevents infinite /// loops where an action callback queues an event that causes the action callback to /// be called again which queues an event... /// /// Note that this limit only applies while the input system is updating. There is no limit /// on the number of events that can be queued outside of this time, but those will be queued /// into the next frame where the setting will apply. /// /// The default value is 1000. /// /// public int maxQueuedEventsPerUpdate { get => m_MaxQueuedEventsPerUpdate; set { if (m_MaxQueuedEventsPerUpdate == value) return; m_MaxQueuedEventsPerUpdate = value; OnChange(); } } /// /// List of device layouts used by the project. /// /// /// This would usually be one of the high-level abstract device layouts. For example, for /// a game that supports touch, gamepad, and keyboard&mouse, the list would be /// { "Touchscreen", "Gamepad", "Mouse", "Keyboard" }. However, nothing prevents the /// the user from adding something a lot more specific. A game that can only be played /// with a DualShock controller could make this list just be { "DualShockGamepad" }, /// for example. /// /// In the editor, we use the information to filter what we display to the user by automatically /// filtering out irrelevant controls in the control picker and such. /// /// The information is also used when a new device is discovered. If the device is not listed /// as supported by the project, it is ignored. /// /// The list is empty by default. An empty list indicates that no restrictions are placed on what /// devices are supported. In this editor, this means that all possible devices and controls are /// shown. /// /// public ReadOnlyArray supportedDevices { get => new ReadOnlyArray(m_SupportedDevices); set { // Detect if there was a change. if (supportedDevices.Count == value.Count) { var hasChanged = false; for (var i = 0; i < supportedDevices.Count; ++i) if (m_SupportedDevices[i] != value[i]) { hasChanged = true; break; } if (!hasChanged) return; } m_SupportedDevices = value.ToArray(); OnChange(); } } /// /// Disables merging of redundant input events (at the moment, only mouse events). /// Disable it if you want to get all events. /// /// /// When using a high frequency mouse, the number of mouse move events in each frame can be /// very large, which can have a negative effect on performance. To help with this, /// merging events can be used which coalesces consecutive mouse move events into a single /// input action update. /// /// For example, if there are one hundred mouse events, but they are all position updates /// with no clicks, and there is an input action callback handler for the mouse position, that /// callback handler will only be called one time in the current frame. Delta and scroll /// values for the mouse will still be accumulated across all mouse events. /// public bool disableRedundantEventsMerging { get => m_DisableRedundantEventsMerging; set { if (m_DisableRedundantEventsMerging == value) return; m_DisableRedundantEventsMerging = value; OnChange(); } } /// /// Enables complexity-based shortcut resolution: composite bindings consume overlapping input using binding-chain depth (complexity), not per-action priority. /// /// /// When enabled and is disabled, actions can exclusively trigger and consume or block other actions sharing the same input. /// For example, when pressing the 'Shift+B' keys, the associated action can trigger while an action bound only to the 'B' key is prevented from triggering at the same time. /// Resolution uses composite complexity (more parts in the composite are considered first). Fewer-part composites do not win over a triggered higher-complexity binding on overlapping controls. /// This works well for shortcut keys; in other cases results may be undesirable, especially when two composites have the same complexity (order is then non-deterministic). /// Conflicts can occur between actions in different action maps (for example UI navigation on arrow keys versus gameplay on the same keys), but not between different action assets. /// When is enabled, this setting does not select the resolution strategy; use for priority-based resolution instead. /// /// public bool shortcutKeysConsumeInput { get => m_ShortcutKeysConsumeInputs; set { if (m_ShortcutKeysConsumeInputs == value) return; m_ShortcutKeysConsumeInputs = value; OnChange(); } } /// /// When enabled, shortcut overlap resolution uses each action's instead of composite complexity. /// /// /// If this is enabled, it takes precedence over for resolution behavior: the system uses priority-based consumption and ordering even when complexity-based consumption is also toggled on. /// Among overlapping actions on the same control, when a higher-priority action reaches , a greater than zero can mark the input event as handled so lower-priority actions are suppressed; priority zero does not. /// Serialized priority values on actions are always kept; when this is off, priorities are not applied at runtime and the Priority field is hidden in the Input Actions editor. /// /// public bool shortcutKeysUseActionPriority { get => m_ShortcutKeysUseActionPriority; set { if (m_ShortcutKeysUseActionPriority == value) return; m_ShortcutKeysUseActionPriority = value; OnChange(); } } /// /// True when overlap resolution should use (monitor ordering and consumption). /// internal bool IsShortcutResolutionUsingActionPriority => m_ShortcutKeysUseActionPriority; /// /// True when overlap resolution should use composite binding complexity (develop behavior), not action priority. /// internal bool IsShortcutResolutionUsingComplexity => m_ShortcutKeysConsumeInputs && !m_ShortcutKeysUseActionPriority; /// /// Modifier composites use ordered evaluation when complexity-based shortcut support is active. /// internal bool IsShortcutComplexityModifierOrderActive => m_ShortcutKeysConsumeInputs && !m_ShortcutKeysUseActionPriority; /// /// Enable or disable an internal feature by its name. /// /// Name of the feature. /// Whether to enable or disable the feature. /// is null or empty. /// /// This method is intended for experimental features. These must be enabled/disabled from code. /// Setting or unsetting a feature flag will not be persisted in an .inputsettings file. /// public void SetInternalFeatureFlag(string featureName, bool enabled) { if (string.IsNullOrEmpty(featureName)) throw new ArgumentNullException(nameof(featureName)); if (m_FeatureFlags == null) m_FeatureFlags = new HashSet(); if (enabled) m_FeatureFlags.Add(featureName.ToUpperInvariant()); else m_FeatureFlags.Remove(featureName.ToUpperInvariant()); OnChange(); } [Tooltip("Determine which type of devices are used by the application. By default, this is empty meaning that all devices recognized " + "by Unity will be used. Restricting the set of supported devices will make only those devices appear in the input system.")] [SerializeField] private string[] m_SupportedDevices; [Tooltip("Determine when Unity processes events. By default, accumulated input events are flushed out before each fixed update and " + "before each dynamic update. This setting can be used to restrict event processing to only where the application needs it.")] [SerializeField] private UpdateMode m_UpdateMode = UpdateMode.ProcessEventsInDynamicUpdate; [SerializeField] private ScrollDeltaBehavior m_ScrollDeltaBehavior = ScrollDeltaBehavior.UniformAcrossAllPlatforms; [SerializeField] private int m_MaxEventBytesPerUpdate = 5 * 1024 * 1024; [SerializeField] private int m_MaxQueuedEventsPerUpdate = 1000; [SerializeField] private bool m_CompensateForScreenOrientation = true; [SerializeField] private BackgroundBehavior m_BackgroundBehavior = BackgroundBehavior.ResetAndDisableNonBackgroundDevices; [SerializeField] private EditorInputBehaviorInPlayMode m_EditorInputBehaviorInPlayMode; [SerializeField] private InputActionPropertyDrawerMode m_InputActionPropertyDrawerMode = InputActionPropertyDrawerMode.Compact; [SerializeField] private float m_DefaultDeadzoneMin = 0.125f; [SerializeField] private float m_DefaultDeadzoneMax = 0.925f; // A setting of 0.5 seems to roughly be what games generally use on the gamepad triggers. // Having a higher value here also obsoletes the need for custom press points on stick buttons // (the up/down/left/right ones). [Min(ButtonControl.kMinButtonPressPoint)] [SerializeField] private float m_DefaultButtonPressPoint = 0.5f; [SerializeField] private float m_ButtonReleaseThreshold = 0.75f; [SerializeField] private float m_DefaultTapTime = 0.2f; [SerializeField] private float m_DefaultSlowTapTime = 0.5f; [SerializeField] private float m_DefaultHoldTime = 0.4f; [SerializeField] private float m_TapRadius = 5; [SerializeField] private float m_MultiTapDelayTime = 0.75f; [SerializeField] private bool m_DisableRedundantEventsMerging = false; [SerializeField] private bool m_ShortcutKeysConsumeInputs = false; // This is the shortcut support from v1.4. Temporarily moved here as an opt-in feature, while it's issues are investigated. [SerializeField] private bool m_ShortcutKeysUseActionPriority = false; [NonSerialized] internal HashSet m_FeatureFlags; internal bool IsFeatureEnabled(string featureName) { return m_FeatureFlags != null && m_FeatureFlags.Contains(featureName.ToUpperInvariant()); } internal void OnChange() { if (InputSystem.settings == this) InputSystem.manager.ApplySettings(); } internal const int s_OldUnsupportedFixedAndDynamicUpdateSetting = 0; /// /// How the input system should update. /// /// /// By default, the input system will run event processing as part of the player loop. In the default configuration, /// the processing will happens once before every every dynamic update (Update), /// i.e. is the default behavior. /// /// There are two types of updates not governed by UpdateMode. One is which /// will always be enabled in the editor and govern input updates for s in /// sync to . /// /// The other update type is . This type of update is enabled and disabled /// automatically in response to whether devices are present requiring this type of update (). This update does not consume extra state. /// /// /// /// /// public enum UpdateMode { // Removed: ProcessEventsInBothFixedAndDynamicUpdate=0 /// /// Automatically run input updates right before every Update. /// /// In this mode, no processing happens specifically for fixed updates. Querying input state in /// FixedUpdate will result in errors being logged in the editor and in /// development builds. In release player builds, the value of the dynamic update state is returned. /// ProcessEventsInDynamicUpdate = 1, /// /// Automatically input run updates right before every FixedUpdate. /// /// In this mode, no processing happens specifically for dynamic updates. Querying input state in /// Update will result in errors being logged in the editor and in /// development builds. In release player builds, the value of the fixed update state is returned. /// ProcessEventsInFixedUpdate, /// /// Do not run updates automatically. In this mode, must be called /// manually to update input. /// /// This mode is most useful for placing input updates in the frame explicitly at an exact location. /// /// Note that failing to call may result in a lot of events /// accumulating or some input getting lost. /// ProcessEventsManually, } /// /// How platform-specific input should be converted when returning delta values for scroll wheel input actions. /// public enum ScrollDeltaBehavior { /// /// The range used for the delta is converted to be uniform across all platforms. /// /// /// The resulting range will be [-1, 1] regardless of the platform used. /// UniformAcrossAllPlatforms = 0, /// /// The range used for the delta is the same as returned by the platform input. /// /// /// The range will typically be [-120, 120] on Windows and [-1, 1] on MacOS and Linux. /// Other platforms may have different ranges. /// KeepPlatformSpecificInputRange = 1 } /// /// Determines how the applications behaves when running in the background. See . /// /// /// Limitations: /// /// Receiving input while the application is not in the foreground is platform and device-dependent, and should not be relied upon. /// IgnoreFocus does not grant the ability to receive input in the background; it only prevents the Input System from resetting/disabling devices on focus changes. /// /// Specifically: /// /// Keyboard: InputSystem doesn't receive events while unfocused. /// Even on platforms where OS-level hooks could technically capture background keyboard input, Unity doesn't forward it to the managed Input System. /// /// Mouse: Only receives events when the cursor is hovering over the application window. /// /// XR HMDs: May continue receiving tracking data while unfocused, depending on the XR runtime. /// These devices report canRunInBackground == true and are the primary use case for ResetAndDisableNonBackgroundDevices, /// which leaves them untouched while resetting everything else. /// /// /// /// /// public enum BackgroundBehavior { /// /// When the application loses focus, issue a call on every that is /// not marked as and then disable the device (see /// and ). Devices that will not be touched and will /// keep running as is. /// /// In effect, this setting will "soft-reset" all devices that cannot receive input while the application does /// not have focus. That is, it will reset all controls that are not marked as /// to their default state. /// /// When the application comes back into focus, all devices that have been reset and disabled will be re-enabled and a synchronization /// request (see ) will be sent to each device. /// /// Devices that are added while the application is running in the background are treated like devices that were already present /// when losing focus. That is, if they cannot run in the background, they will be disabled until focus comes back. /// /// Note that the resets will cancel s that are in progress from controls on devices that are being reset. /// ResetAndDisableNonBackgroundDevices = 0, /// /// Like but instead treat all devices as having /// return false. This effectively means that all input is silenced while the application is running in the background. /// ResetAndDisableAllDevices = 1, /// /// Ignore all changes in focus and leave devices untouched. This also disables focus checks in . /// This mode doesn't disable devices when the application loses focus. It also doesn't reset or sync device state on focus changes. /// As a result, input controls may retain a stale state after focus transitions. /// For example, if a key is held when the application loses focus and released while unfocused, the Input System still reports that key as pressed /// when the focus returns. This is the expected behavior, not a bug. /// If you need a reliable state after focus changes, use ResetAndDisableNonBackgroundDevices (default) or ResetAndDisableAllDevices. /// IgnoreFocus = 2, } /// /// Determines how player focus is handled with respect to input when we are in play mode in the editor. /// See . The setting does not have an effect /// when the editor is not in play mode. /// public enum EditorInputBehaviorInPlayMode { /// /// When the game view does not have focus, input from devices (such as and ) /// is routed to the editor and not visible in player code. Input from devices such as s will continue to /// go to the game regardless of which EditorWindow is focused. /// /// This is the default. It makes sure that the devices that are used with the editor UI respect EditorWindow focus and thus /// do not lead to accidental inputs affecting the game. While at the same time letting all other input get through to the game. /// It does, however, mean that no other EditorWindow can tap input from these devices (such as s and s). /// PointersAndKeyboardsRespectGameViewFocus, /// /// When the game view does not have focus, all input is routed to the editor (and thus EditorWindows). No input /// is received in the game regardless of the type of device generating it. /// AllDevicesRespectGameViewFocus, /// /// All input is going to the game at all times. This most closely aligns input behavior in the editor with that in players. /// will be respected as in the player and devices may thus be disabled in the runtime based on Game View focus. /// AllDeviceInputAlwaysGoesToGameView, } /// /// Determines how the Inspector window displays fields. /// /// public enum InputActionPropertyDrawerMode { /// /// Display the property in a compact format, using a minimal number of lines. /// Toggling between a reference to an input action in an asset and a directly serialized input action /// is done using a dropdown menu. /// Compact, /// /// Display the effective action underlying the property, using multiple lines. /// Toggling between a reference to an input action in an asset and a directly serialized input action /// is done using a property that is always visible. /// /// /// This mode could be useful if you want to see or revert prefab overrides and hide the field that is ignored. /// MultilineEffective, /// /// Display both the input action and external reference underlying the property. /// Toggling between a reference to an input action in an asset and a directly serialized input action /// is done using a property that is always visible. /// /// /// This mode could be useful if you want to see both values of the property without needing to toggle Use Reference. /// MultilineBoth, } #if UNITY_EDITOR /// /// Determines if we should render the UI with IMGUI even if an UI Toolkit UI is available. /// /// This should be used when writing a custom to : /// * support inspector view which only work in IMGUI for now. /// * prevent the UI to be rendered in IMGUI and UI Toolkit in the Input Actions Editor window. /// public bool useIMGUIEditorForAssets => (s_GetIsInspectorIndented?.Invoke() == true) || IsFeatureEnabled(InputFeatureNames.kUseIMGUIEditorForAssets); internal static Func s_GetIsInspectorIndented; #endif private static bool CompareFloats(float a, float b) { return (a - b) <= float.Epsilon; } private static bool CompareSets(ReadOnlyArray a, ReadOnlyArray b) { if (ReferenceEquals(null, a)) return ReferenceEquals(null, b); if (ReferenceEquals(null, b)) return false; for (var i = 0; i < a.Count; ++i) { bool existsInB = false; for (var j = 0; j < b.Count; ++j) { if (a[i].Equals(b[j])) { existsInB = true; break; } } if (!existsInB) return false; } return true; } private static bool CompareFeatureFlag(InputSettings a, InputSettings b, string featureName) { return a.IsFeatureEnabled(featureName) == b.IsFeatureEnabled(featureName); } internal static bool AreEqual(InputSettings a, InputSettings b) { if (ReferenceEquals(null, a)) return ReferenceEquals(null, b); if (ReferenceEquals(null, b)) return false; if (ReferenceEquals(a, b)) return true; return (a.updateMode == b.updateMode) && (a.compensateForScreenOrientation == b.compensateForScreenOrientation) && // Ignoring filterNoiseOnCurrent since deprecated CompareFloats(a.defaultDeadzoneMin, b.defaultDeadzoneMin) && CompareFloats(a.defaultDeadzoneMax, b.defaultDeadzoneMax) && CompareFloats(a.defaultButtonPressPoint, b.defaultButtonPressPoint) && CompareFloats(a.buttonReleaseThreshold, b.buttonReleaseThreshold) && CompareFloats(a.defaultTapTime, b.defaultTapTime) && CompareFloats(a.defaultSlowTapTime, b.defaultSlowTapTime) && CompareFloats(a.defaultHoldTime, b.defaultHoldTime) && CompareFloats(a.tapRadius, b.tapRadius) && CompareFloats(a.multiTapDelayTime, b.multiTapDelayTime) && a.backgroundBehavior == b.backgroundBehavior && a.editorInputBehaviorInPlayMode == b.editorInputBehaviorInPlayMode && a.inputActionPropertyDrawerMode == b.inputActionPropertyDrawerMode && a.maxEventBytesPerUpdate == b.maxEventBytesPerUpdate && a.maxQueuedEventsPerUpdate == b.maxQueuedEventsPerUpdate && CompareSets(a.supportedDevices, b.supportedDevices) && a.disableRedundantEventsMerging == b.disableRedundantEventsMerging && a.shortcutKeysConsumeInput == b.shortcutKeysConsumeInput && a.shortcutKeysUseActionPriority == b.shortcutKeysUseActionPriority && CompareFeatureFlag(a, b, InputFeatureNames.kUseOptimizedControls) && CompareFeatureFlag(a, b, InputFeatureNames.kUseReadValueCaching) && CompareFeatureFlag(a, b, InputFeatureNames.kParanoidReadValueCachingChecks) && CompareFeatureFlag(a, b, InputFeatureNames.kDisableUnityRemoteSupport) && CompareFeatureFlag(a, b, InputFeatureNames.kRunPlayerUpdatesInEditMode) && CompareFeatureFlag(a, b, InputFeatureNames.kUseIMGUIEditorForAssets); } } }