diff --git a/.github/codecov.yml b/.github/codecov.yml index 9f4821c944..6d182ac407 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -9,14 +9,21 @@ coverage: round: down range: "50...70" status: - patch: true + patch: + default: + target: auto + threshold: 1% + base: auto + if_ci_failed: success + informational: true + only_pulls: true default_rules: flag_coverage_not_uploaded_behavior: exclude project: default: target: auto threshold: 1% - base: auto + base: auto if_ci_failed: success informational: true only_pulls: true diff --git a/Assets/Tests/InputSystem/CoreTests_Editor.cs b/Assets/Tests/InputSystem/CoreTests_Editor.cs index 0a74266c6b..747941f235 100644 --- a/Assets/Tests/InputSystem/CoreTests_Editor.cs +++ b/Assets/Tests/InputSystem/CoreTests_Editor.cs @@ -2893,9 +2893,9 @@ public void Editor_WhenRunUpdatesInEditModeIsEnabled_InputActionsTriggerInEditMo private static void DisableProjectWideActions() { #if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS - // If the system has project-wide input actions they will also trigger enable/disable via - // play mode change triggers above. Hence we adjust extra variable to compensate of - // state allocated by project-wide actions. + // If the system has project-wide input actions they will start enabled once InputSystem.Reset() is called and + // be disabled entering EditMode. Hence, we adjust extra variable to compensate ofstate allocated by + // project-wide actions. if (InputSystem.actions) { Assert.That(InputActionState.s_GlobalState.globalList.length, Is.EqualTo(1)); @@ -2905,6 +2905,39 @@ private static void DisableProjectWideActions() #endif } + [Test] + [Category("Editor")] + public void Editor_InitializeInEditor_EnablesProjectWideActions() + { + #if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS + if (InputSystem.actions != null) + { + // Asserts that project wide actions are enabled by default. + // Before the test is run, InputSystem.Reset() is called which will enable them. + // It can be interpreted as a mock of the behavior that happens when `InitializeInEditor()` is called. + Assert.That(InputSystem.actions.enabled, Is.True); + + // Calling exit play mode callbacks will disable them + InputSystem.OnPlayModeChange(PlayModeStateChange.ExitingPlayMode); + InputSystem.OnPlayModeChange(PlayModeStateChange.EnteredEditMode); + + Assert.That(InputSystem.actions.enabled, Is.False); + + // Calling enter play mode callbacks will not re-enable them per default. They are only + // enabled when `InputSystem.InitializeInEditor()` is called, which happens before these callbacks. + // Note: Project-wide actions are disabled at this point. These next lines are added to make sure we + // establish behavior that project-wide actions should be enabled only once + // `InputSystem.InitializeInEditor()` is called. Before this test was introduced, project-wide actions were + // enabled after entering play mode again which would lead to a different behavior than Player + // builds. + InputSystem.OnPlayModeChange(PlayModeStateChange.ExitingEditMode); + InputSystem.OnPlayModeChange(PlayModeStateChange.EnteredPlayMode); + + Assert.That(InputSystem.actions.enabled, Is.False); + } + #endif + } + [Test] [Category("Editor")] public void Editor_LeavingPlayMode_DestroysAllActionStates() @@ -2918,6 +2951,15 @@ public void Editor_LeavingPlayMode_DestroysAllActionStates() // Enter play mode. InputSystem.OnPlayModeChange(PlayModeStateChange.ExitingEditMode); + +#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS + + // This simulates enabling project-wide actions, which is done before just before entering play mode, + // called from InputSystem.InitializeInEditor(). + if (InputSystem.actions) + InputSystem.actions.Enable(); +#endif + InputSystem.OnPlayModeChange(PlayModeStateChange.EnteredPlayMode); DisableProjectWideActions(); @@ -2934,7 +2976,8 @@ public void Editor_LeavingPlayMode_DestroysAllActionStates() InputSystem.OnPlayModeChange(PlayModeStateChange.EnteredEditMode); Assert.That(InputActionState.s_GlobalState.globalList.length, Is.Zero); - Assert.That(InputSystem.s_Manager.m_StateChangeMonitors[0].listeners[0].control, Is.Null); // Won't get removed, just cleared. + // Won't get removed, just cleared. + Assert.That(InputSystem.s_Manager.m_StateChangeMonitors[0].listeners[0].control, Is.Null); } [Test] diff --git a/Assets/Tests/InputSystem/CoreTests_ProjectWideActions.cs b/Assets/Tests/InputSystem/CoreTests_ProjectWideActions.cs index 93fea59859..4d9263696f 100644 --- a/Assets/Tests/InputSystem/CoreTests_ProjectWideActions.cs +++ b/Assets/Tests/InputSystem/CoreTests_ProjectWideActions.cs @@ -4,11 +4,12 @@ using NUnit.Framework; using UnityEngine.InputSystem; using UnityEngine.TestTools; +using UnityEngine; +using System.Collections; #if UNITY_EDITOR using System.IO; using UnityEditor; -using UnityEngine; using UnityEngine.InputSystem.Editor; #endif // UNITY_EDITOR @@ -101,10 +102,10 @@ public void ProjectWideActions_IsAutomaticallyAssignedFromPersistedAsset_WhenRun Assert.That(InputSystem.actions, Is.Not.Null); // In editor play-mode we may as well verify that the asset has the expected name - #if UNITY_EDITOR +#if UNITY_EDITOR var expectedName = InputActionImporter.NameFromAssetPath(AssetDatabase.GetAssetPath(InputSystem.actions)); Assert.That(InputSystem.actions.name, Is.EqualTo(expectedName)); - #endif +#endif } [Test] @@ -140,6 +141,61 @@ public void ProjectWideActions_AppearInEnabledActions() // TODO Modifying the actions object after being assigned should also enable newly added actions? } + + [Category(TestCategory)] + [Test] + [TestCase("Player", true, Description = "PlayerInput using project-wide actions can have default action map set " + + "enabled, and all others disabled.")] + [TestCase(null, false, Description = "PlayerInput using project wide actions has all action maps of project-wide " + + "actions disabled, if there is no default action map assigned.")] + public void ProjectWideActions_CanEnableCurrentActionMapOfPlayerInput(string actionMapName, bool expectedResult) + { + var keyboard = InputSystem.AddDevice(); + var go = new GameObject("PlayerInput"); + + go.SetActive(false); + var playerInput = go.AddComponent(); + playerInput.actions = InputSystem.actions; + // Default action map to be enabled. All others are expected to be disabled since InputSystem.actions.Disable() + // will be called. + playerInput.defaultActionMap = actionMapName; + + // PWA actions assigned to playerInput start enabled + Assert.That(playerInput.actions.enabled, Is.True); + Assert.That(ReferenceEquals(playerInput.actions, InputSystem.actions)); + +#if UNITY_EDITOR + InputSystem.OnPlayModeChange(PlayModeStateChange.ExitingEditMode); +#endif + + // This makes sure to call PlayerInput.OnEnable() + go.SetActive(true); + + // This mimics usings to disabling actions on Start/Awake. + InputSystem.actions.Disable(); + + if (!string.IsNullOrEmpty(actionMapName)) + playerInput.SwitchCurrentActionMap("Player"); + + Assert.That(playerInput.actions.enabled, Is.EqualTo(expectedResult)); + + // We do this on the editor to make sure project-wide actions maintain the enabled state + // after entering PlayMode. +#if UNITY_EDITOR + InputSystem.OnPlayModeChange(PlayModeStateChange.EnteredPlayMode); + Assert.That(playerInput.actions.enabled, Is.EqualTo(expectedResult)); +#endif + + if (!string.IsNullOrEmpty(actionMapName)) + Assert.That(playerInput.currentActionMap.enabled, Is.EqualTo(expectedResult)); + + // Check state of all action maps in the asset + Assert.That(InputSystem.actions.FindActionMap("Player").enabled, Is.EqualTo(expectedResult)); + Assert.That(InputSystem.actions.FindActionMap("UI").enabled, Is.False); + + //NOTE: Asset actions are considered enabled even if a single action map is enabled + Assert.That(playerInput.actions.enabled, Is.EqualTo(expectedResult)); + } } #endif diff --git a/Assets/Tests/InputSystem/Plugins/PlayerInputTests.cs b/Assets/Tests/InputSystem/Plugins/PlayerInputTests.cs index 16e927676f..b0977877e5 100644 --- a/Assets/Tests/InputSystem/Plugins/PlayerInputTests.cs +++ b/Assets/Tests/InputSystem/Plugins/PlayerInputTests.cs @@ -55,7 +55,7 @@ public void PlayerInput_CanInstantiatePlayer() Assert.That(player, Is.Not.Null); Assert.That(player.playerIndex, Is.EqualTo(0)); - Assert.That(player.actions.actionMaps.Count, Is.EqualTo(prefabPlayerInput.actions.actionMaps.Count)); + Assert.That(player.actions, Is.SameAs(prefabPlayerInput.actions)); Assert.That(player.devices, Is.EquivalentTo(new[] { gamepad })); Assert.That(player.currentControlScheme, Is.EqualTo("Gamepad")); } @@ -395,21 +395,6 @@ public void PlayerInput_CanAssignActionsToPlayer() Assert.That(playerInput.actions.actionMaps[0].name, Is.EqualTo(actions.actionMaps[0].name)); } - [Test] - [Category("PlayerInput")] - public void PlayerInput_CopiesActionAssetForFirstPlayer() - { - var go = new GameObject(); - var playerInput = go.AddComponent(); - - var actions = InputActionAsset.FromJson(kActions); - playerInput.actions = actions; - - Assert.That(playerInput.actions.actionMaps.Count, Is.EqualTo(actions.actionMaps.Count)); - Assert.That(playerInput.actions.actionMaps[0].name, Is.EqualTo(actions.actionMaps[0].name)); - Assert.That(playerInput.actions.GetInstanceID(), !Is.EqualTo(actions.GetInstanceID())); - } - [Test] [Category("PlayerInput")] public void PlayerInput_AssigningNewActionsToPlayer_DisablesExistingActions() @@ -424,12 +409,12 @@ public void PlayerInput_AssigningNewActionsToPlayer_DisablesExistingActions() playerInput.actions = actions1; Assert.That(playerInput.actions.actionMaps[0].enabled, Is.True); - Assert.That(actions1.actionMaps[0].enabled, Is.False); + Assert.That(actions2.actionMaps[0].enabled, Is.False); playerInput.actions = actions2; - Assert.That(actions2.actionMaps[0].enabled, Is.False); Assert.That(playerInput.actions.actionMaps[0].enabled, Is.True); + Assert.That(actions1.actionMaps[0].enabled, Is.False); } [Test] @@ -497,6 +482,22 @@ public void PlayerInput_DuplicatingActions_AssignsNewInstanceToUI() Assert.That(playerInput2.actions, Is.SameAs(ui2.actionsAsset)); } + [Test] + [Category("PlayerInput")] + public void PlayerInput_ActionFromCodeGeneratedActionIsTheSameBeingReferenced() + { + var go = new GameObject(); + + var playerInput = go.AddComponent(); + var ui = go.AddComponent(); + var defaultActions = new DefaultInputActions(); + + playerInput.uiInputModule = ui; + playerInput.actions = defaultActions.asset; + + Assert.That(defaultActions.UI.Submit == playerInput.actions.FindAction("Submit"), Is.True); + } + [Test] [Category("PlayerInput")] public void PlayerInput_CanPassivateAndReactivateInputBySendingMessages() diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index 98152e1e3c..280718a4f7 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -31,6 +31,7 @@ however, it has to be formatted properly to pass verification tests. - Fixed PlayerInput component automatically switching away from the default ActionMap set to 'None'. - Fixed a console error being shown when targeting visionOS builds in 2022.3. - Fixed a Tap Interaction issue with analog controls. The Tap interaction would keep re-starting after timeout. [ISXB-627](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-627) +- Fixed PlayerInput component not working with C# Wrappers (ISXB-1535). This reverted changes done to fix [ISXB-920](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-920) but users can now fix it themselves. ## [1.14.0] - 2025-03-20 diff --git a/Packages/com.unity.inputsystem/Documentation~/PlayerInput.md b/Packages/com.unity.inputsystem/Documentation~/PlayerInput.md index f877b89d99..6036f935e7 100644 --- a/Packages/com.unity.inputsystem/Documentation~/PlayerInput.md +++ b/Packages/com.unity.inputsystem/Documentation~/PlayerInput.md @@ -37,21 +37,21 @@ Each `PlayerInput` corresponds to one [`InputUser`](UserManagement.md). You can To get started using the Player Input component, use the following steps: 1. [Add](https://docs.unity3d.com/Manual/UsingComponents.html) a **Player Input** component to a GameObject. This would usually be the GameObject that represents the player in your game. -1. Assign your [Action Asset](ActionAssets.md) to the **Actions** field. This is usually the default project-wide action asset named "InputSystem_Actions" -1. Set up Action responses, by selecting a **Behaviour** type from the Behaviour menu. The Behaviour type you select affects how you should implement the methods that handle your Action responses. See the [notification behaviors](#notification-behaviors) section further down for details.

![PlayerInput Notification Behavior](Images/PlayerInputNotificationBehaviors.png)

- +2. Assign your [Action Asset](ActionAssets.md) to the **Actions** field. This is usually the default project-wide action asset named "InputSystem_Actions" +> Note: Currently, when using project-wide actions all the action maps are enabled by default. It is advisible to manually disable them and manually enable the default map that **Player Input** during `Start()`. +3. Set up Action responses, by selecting a **Behaviour** type from the Behaviour menu. The Behaviour type you select affects how you should implement the methods that handle your Action responses. See the [notification behaviors](#notification-behaviors) section further down for details.

![PlayerInput Notification Behavior](Images/PlayerInputNotificationBehaviors.png)

## Configuring the Player Input component You can use the following properties to configure `PlayerInput`: -|Property|Description| -|--------|-----------| -|[`Actions`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_actions)|The set of [Input Actions](Actions.md) associated with the player. Typically you would set this to Project-Wide Actions, however you can assign an [ActionAsset](ActionAssets.md) reference here). To receive input, each player must have an associated set of Actions. See documentation on [Actions](#actions) for details.| -|[`Default Control Scheme`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_defaultControlScheme)|Which [Control Scheme](ActionBindings.md#control-schemes) (from what is defined in [`Actions`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_actions)) to enable by default.| -|[`Default Action Map`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_defaultActionMap)|Which [Action Map](Actions.md#overview) in [`Actions`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_actions) to enable by default. If set to `None`, then the player starts with no Actions being enabled.| -|[`Camera`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_camera)|The individual camera associated with the player. This is only required when employing [split-screen](PlayerInputManager.md#split-screen) setups and has no effect otherwise.| -|[`Behavior`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_notificationBehavior)|How the `PlayerInput` component notifies game code about things that happen with the player. See documentation on [notification behaviors](#notification-behaviors).| +| Property | Description | +| ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [`Actions`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_actions) | The set of [Input Actions](Actions.md) associated with the player. Typically you would set this to Project-Wide Actions, however you can assign an [ActionAsset](ActionAssets.md) reference here). To receive input, each player must have an associated set of Actions. See documentation on [Actions](#actions) for details. | +| [`Default Control Scheme`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_defaultControlScheme) | Which [Control Scheme](ActionBindings.md#control-schemes) (from what is defined in [`Actions`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_actions)) to enable by default. | +| [`Default Action Map`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_defaultActionMap) | Which [Action Map](Actions.md#overview) in [`Actions`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_actions) to enable by default. If set to `None`, then the player starts with no Actions being enabled. | +| [`Camera`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_camera) | The individual camera associated with the player. This is only required when employing [split-screen](PlayerInputManager.md#split-screen) setups and has no effect otherwise. | +| [`Behavior`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_notificationBehavior) | How the `PlayerInput` component notifies game code about things that happen with the player. See documentation on [notification behaviors](#notification-behaviors). | ### Actions @@ -63,6 +63,21 @@ The simplest workflow is to use the project-wide actions defined in the [Input A #### Enabling and disabling Actions The Player Input component automatically handles enabling and disabling Actions, and also handles installing [callbacks](RespondingToActions.md#responding-to-actions-using-callbacks) on the Actions. When multiple Player Input components use the same Actions, the components automatically create [private copies of the Actions](RespondingToActions.md#using-actions-with-multiple-players). This is why, when writing input code that works with the PlayerInput component, you should not use `InputSystem.actions` because this references the "singleton" copy of the actions rather than the specific private copy associated with the PlayerInput instance you are coding for. +While we advise against using it, if you **really need or want** to use `InputSystem.actions` for single player use cases, it is advisible to manually disable them and manually enable the default map that **Player Input** sets, during `Start()`, like so: +```csharp +public class MyPlayerScript : MonoBehaviour +{ + PlayerInput playerInput; + + void Start() + { + playerInput = GetComponent(); + InputSystem.actions.Disable(); + playerInput.currentActionMap?.Enable(); + } +} + +``` When first enabled, the Player Input component enables all Actions from the the [`Default Action Map`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_defaultActionMap). If no default Action Map exists, the Player Input component does not enable any Actions. To manually enable Actions, you can call [`Enable`](../api/UnityEngine.InputSystem.InputActionMap.html#UnityEngine_InputSystem_InputActionMap_Enable) and [`Disable`](../api/UnityEngine.InputSystem.InputActionMap.html#UnityEngine_InputSystem_InputActionMap_Disable) on the Action Maps or Actions, like you would do [without `PlayerInput`](Actions.md). To check which Action Map is currently enabled, or to switch to a different one, use the [`PlayerInput.currentActionMap`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_currentActionMap) property. To switch Action Maps with an Action Map name, you can also call [`PlayerInput.SwitchCurrentActionMap`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_SwitchCurrentActionMap_System_String_). @@ -126,19 +141,19 @@ You can use the [`Behavior`](../api/UnityEngine.InputSystem.PlayerInput.html#Uni The following options are available: -|Behavior|Description| -|--------|-----------| -|[`Send Messages`](../api/UnityEngine.InputSystem.PlayerNotifications.html)|Uses [`GameObject.SendMessage`](https://docs.unity3d.com/ScriptReference/GameObject.SendMessage.html) on the `GameObject` that the `PlayerInput` component belongs to.| -|[`Broadcast Messages`](../api/UnityEngine.InputSystem.PlayerNotifications.html)|Uses [`GameObject.BroadcastMessage`](https://docs.unity3d.com/ScriptReference/GameObject.BroadcastMessage.html) on the `GameObject` that the `PlayerInput` component belongs to. This broadcasts the message down the `GameObject` hierarchy.| -|[`Invoke Unity Events`](../api/UnityEngine.InputSystem.PlayerNotifications.html)|Uses a separate [`UnityEvent`](https://docs.unity3d.com/ScriptReference/Events.UnityEvent.html) for each individual type of message. When this is selected, the events available on the `PlayerInput` are accessible from the __Events__ foldout. The argument received by events triggered for Actions is the same as the one received by [`started`, `performed`, and `canceled` callbacks](RespondingToActions.md#action-callbacks).

![PlayerInput UnityEvents](Images/MyPlayerActionEvents.png)| -|[`Invoke CSharp Events`](../api/UnityEngine.InputSystem.PlayerNotifications.html)|Similar to `Invoke Unity Events`, except that the events are plain C# events available on the `PlayerInput` API. You cannot configure these from the Inspector. Instead, you have to register callbacks for the events in your scripts.

The following events are available:

  • [`onActionTriggered`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_onActionTriggered) (collective event for all actions on the player)
  • [`onDeviceLost`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_onDeviceLost)
  • [`onDeviceRegained`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_onDeviceRegained)
| +| Behavior | Description | +| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [`Send Messages`](../api/UnityEngine.InputSystem.PlayerNotifications.html) | Uses [`GameObject.SendMessage`](https://docs.unity3d.com/ScriptReference/GameObject.SendMessage.html) on the `GameObject` that the `PlayerInput` component belongs to. | +| [`Broadcast Messages`](../api/UnityEngine.InputSystem.PlayerNotifications.html) | Uses [`GameObject.BroadcastMessage`](https://docs.unity3d.com/ScriptReference/GameObject.BroadcastMessage.html) on the `GameObject` that the `PlayerInput` component belongs to. This broadcasts the message down the `GameObject` hierarchy. | +| [`Invoke Unity Events`](../api/UnityEngine.InputSystem.PlayerNotifications.html) | Uses a separate [`UnityEvent`](https://docs.unity3d.com/ScriptReference/Events.UnityEvent.html) for each individual type of message. When this is selected, the events available on the `PlayerInput` are accessible from the __Events__ foldout. The argument received by events triggered for Actions is the same as the one received by [`started`, `performed`, and `canceled` callbacks](RespondingToActions.md#action-callbacks).

![PlayerInput UnityEvents](Images/MyPlayerActionEvents.png) | +| [`Invoke CSharp Events`](../api/UnityEngine.InputSystem.PlayerNotifications.html) | Similar to `Invoke Unity Events`, except that the events are plain C# events available on the `PlayerInput` API. You cannot configure these from the Inspector. Instead, you have to register callbacks for the events in your scripts.

The following events are available:

  • [`onActionTriggered`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_onActionTriggered) (collective event for all actions on the player)
  • [`onDeviceLost`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_onDeviceLost)
  • [`onDeviceRegained`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_onDeviceRegained)
| In addition to per-action notifications, `PlayerInput` sends the following general notifications: -|Notification|Description| -|------------|-----------| -|[`DeviceLostMessage`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_DeviceLostMessage)|The player has lost one of the Devices assigned to it. This can happen, for example, if a wireless device runs out of battery.| -|[`DeviceRegainedMessage`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_DeviceRegainedMessage)|Notification that triggers when the player recovers from Device loss and is good to go again.| +| Notification | Description | +| ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | +| [`DeviceLostMessage`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_DeviceLostMessage) | The player has lost one of the Devices assigned to it. This can happen, for example, if a wireless device runs out of battery. | +| [`DeviceRegainedMessage`](../api/UnityEngine.InputSystem.PlayerInput.html#UnityEngine_InputSystem_PlayerInput_DeviceRegainedMessage) | Notification that triggers when the player recovers from Device loss and is good to go again. | ### Device assignments diff --git a/Packages/com.unity.inputsystem/InputSystem/InputSystem.cs b/Packages/com.unity.inputsystem/InputSystem/InputSystem.cs index 1ebb0f44bf..10b5dfa98e 100644 --- a/Packages/com.unity.inputsystem/InputSystem/InputSystem.cs +++ b/Packages/com.unity.inputsystem/InputSystem/InputSystem.cs @@ -3015,16 +3015,10 @@ internal static bool ShouldDrawWarningIconForBinding(string bindingPath) #region Actions #if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS - // EnteredEditMode Occurs during the next update of the Editor application if it is in edit mode and was previously in play mode. - // ExitingEditMode Occurs when exiting edit mode, before the Editor is in play mode. - // EnteredPlayMode Occurs during the next update of the Editor application if it is in play mode and was previously in edit mode. - // ExitingPlayMode Occurs when exiting play mode, before the Editor is in edit mode. - // - // Using the EnteredEditMode / EnteredPlayMode states to transition the actions' enabled - // state ensures that the they are active in all of these MonoBehavior methods: - // - // Awake() / Start() / OnEnable() / OnDisable() / OnDestroy() - // + + // This is called from InitializeInEditor() and InitializeInPlayer() to make sure + // project-wide actions are all active in they are active in all of these MonoBehavior methods: + // Awake() / Start() / OnEnable() / OnDisable() / OnDestroy() private static void EnableActions() { #if UNITY_EDITOR @@ -3408,7 +3402,6 @@ public static int ListEnabledActions(List actions) #endregion - /// /// The current version of the input system package. /// @@ -3651,9 +3644,7 @@ internal static void OnPlayModeChange(PlayModeStateChange change) case PlayModeStateChange.EnteredPlayMode: s_SystemObject.enterPlayModeTime = InputRuntime.s_Instance.currentTime; s_Manager.SyncAllDevicesAfterEnteringPlayMode(); -#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS - EnableActions(); -#endif // UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS + break; case PlayModeStateChange.ExitingPlayMode: @@ -3911,8 +3902,7 @@ private static void Reset(bool enableRemoting = false, IInputRuntime runtime = n InputUser.ResetGlobals(); EnhancedTouchSupport.Reset(); - // This is the point where we initialise project-wide actions for the Editor, Editor Tests and Player Tests. - // Note this is too early for editor ! actions is not setup yet. + // This is the point where we initialise project-wide actions for the Editor Play-mode, Editor Tests and Player Tests. #if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS EnableActions(); #endif diff --git a/Packages/com.unity.inputsystem/InputSystem/Plugins/PlayerInput/PlayerInput.cs b/Packages/com.unity.inputsystem/InputSystem/Plugins/PlayerInput/PlayerInput.cs index 00c09d7bed..32ca9992e3 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Plugins/PlayerInput/PlayerInput.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Plugins/PlayerInput/PlayerInput.cs @@ -342,14 +342,8 @@ public InputActionAsset actions UninitializeActions(); } - var didChange = m_Actions != null; - m_Actions = value; - if (didChange || m_Enabled) - // copy action asset for the first player so that the original asset stays untouched - CopyActionAssetAndApplyBindingOverrides(); - if (m_Enabled) { ClearCaches(); @@ -1810,13 +1804,6 @@ void Reset() #endif - private void Awake() - { - // If an action asset is assigned copy it to avoid modifying the original asset. - if (m_Actions != null) - CopyActionAssetAndApplyBindingOverrides(); - } - private void OnEnable() { m_Enabled = true; diff --git a/Packages/com.unity.inputsystem/InputSystem/Plugins/PlayerInput/PlayerInputEditor.cs b/Packages/com.unity.inputsystem/InputSystem/Plugins/PlayerInput/PlayerInputEditor.cs index f6f36f6251..baea5ef47f 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Plugins/PlayerInput/PlayerInputEditor.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Plugins/PlayerInput/PlayerInputEditor.cs @@ -80,6 +80,22 @@ public override void OnInspectorGUI() EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(m_ActionsProperty); var actionsWereChanged = false; + +#if UNITY_INPUT_SYSTEM_PROJECT_WIDE_ACTIONS + // Check for if we're using project-wide actions to raise a warning message. + if (m_ActionsProperty.objectReferenceValue != null) + { + InputActionAsset actions = m_ActionsProperty.objectReferenceValue as InputActionAsset; + if (actions == InputSystem.actions) + { + EditorGUILayout.HelpBox("Project-wide actions asset is not recommended to be used with Player " + + "Input because it is a singleton reference and all actions maps are enabled by default.\r\n" + + "You should manually disable all action maps on Start() and " + + "manually enable the default action map.", + MessageType.Warning); + } + } +#endif if (EditorGUI.EndChangeCheck() || !m_ActionAssetInitialized || CheckIfActionAssetChanged()) { OnActionAssetChange(); @@ -120,7 +136,6 @@ public override void OnInspectorGUI() // Restore the initial color GUI.backgroundColor = currentBg; - rect = EditorGUILayout.GetControlRect(); label = EditorGUI.BeginProperty(rect, m_AutoSwitchText, m_NeverAutoSwitchControlSchemesProperty); var neverAutoSwitchValueOld = m_NeverAutoSwitchControlSchemesProperty.boolValue;