Skip to content

NEW: (ISXB-1524, ISX-2325, revisiting ISXB-1396) Fix for rebinding issues related to incorrect event suppression + Changed Rebinding Sample #2168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 97 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
e5509ff
Debug files
ekcoh Apr 9, 2025
58ee7a8
Merge branch 'develop' into ekcoh/rebinding-issues-events
ekcoh Apr 14, 2025
d323b9b
Added debug script to scene
ekcoh Apr 14, 2025
da35c49
Added wait to RebindActionUI.cs
ekcoh Apr 15, 2025
93de642
Added input event handled policy run-time setting
ekcoh Apr 22, 2025
59b2659
wip
ekcoh Apr 23, 2025
e4e57cf
Modified handled evaluation in state monitors. Formatting.
ekcoh Apr 23, 2025
00abdcf
Renamed variable
ekcoh Apr 23, 2025
9bdd2d2
Refactoring of names
ekcoh Apr 23, 2025
71e7b61
Updated rebinding UI sample to use new feature (handling policy)
ekcoh Apr 23, 2025
b50d660
Undo of previous change
ekcoh Apr 23, 2025
9c6b2d8
Undo previous change
ekcoh Apr 23, 2025
2d195ed
Made input manager property internal for now
ekcoh Apr 23, 2025
f9c61f5
Attempt to fix xml syntax error for doc
ekcoh Apr 23, 2025
10d2579
Updated changelog
ekcoh Apr 23, 2025
21bd4a8
Merge branch 'develop' into ekcoh/rebinding-issues-events
ekcoh Apr 24, 2025
edbdbcf
Removed ActionDebug script from branch
ekcoh Apr 24, 2025
1baba6c
Undo changes to UI sample actions
ekcoh Apr 24, 2025
b7d8a10
Removed debug comments
ekcoh Apr 24, 2025
69aa686
Formatting
ekcoh Apr 24, 2025
7d07d89
Undo debug comment
ekcoh Apr 24, 2025
eed66dc
Further tweaks of logic
ekcoh Apr 24, 2025
3dfda93
Merge branch 'develop' into ekcoh/rebinding-issues-events
ekcoh Apr 28, 2025
c39c1c0
Fixed formatting
ekcoh Apr 28, 2025
97b41f9
Merge branch 'ekcoh/rebinding-issues-events' of github.com:Unity-Tech…
ekcoh Apr 28, 2025
b82cf28
Expanded Rebinding example to show how actions fire in relation to input
ekcoh Jun 18, 2025
d1932d5
Merge branch 'develop' into ekcoh/rebinding-issues-events
ekcoh Jun 18, 2025
3ad7c58
Improvements to rebinding sample to increase visibility of potential …
ekcoh Jun 24, 2025
200b123
Minor changes to sample scene, added delta rebind
ekcoh Jun 24, 2025
85c8023
Merge branch 'develop' into ekcoh/rebinding-issues-events
ekcoh Jun 24, 2025
74ef71a
Updated CHANGELOG.md
ekcoh Jun 24, 2025
eaa9295
Removed policy property from InputSystem and made the enum type inter…
ekcoh Jun 24, 2025
3191c2e
Reformatted files
ekcoh Jun 24, 2025
8500e3e
Minor tweaks to sample, expanded test coverage, temporary avoid deser…
ekcoh Jun 25, 2025
ca3e1cc
Renamed files, converted action indicators to prefabs and replaced th…
ekcoh Jun 25, 2025
90a9a24
Tweaks to sample, adding missing namespace, changed game manager to u…
ekcoh Jun 25, 2025
40771cb
Clean-up of rebinding sample
ekcoh Jun 25, 2025
af8ad8b
Cleanup of rebinding sample
ekcoh Jun 25, 2025
f3fb1f7
Formatting
ekcoh Jun 25, 2025
f98f4ec
Minor tweaks to rebinding sample and added support for showing disabl…
ekcoh Jun 25, 2025
0a39dd7
Remove code explicitly disabling UI map from rebinding sample since i…
ekcoh Jun 25, 2025
93c7942
Formatting
ekcoh Jun 25, 2025
20e6920
Removed debug script
ekcoh Jun 25, 2025
1e95882
Restored deserialization of setting
ekcoh Jun 25, 2025
87a5590
Removed obsolete editor code and simplified game manager
ekcoh Jun 25, 2025
211bd8a
Removed TODO
ekcoh Jun 25, 2025
f82d27a
Merge branch 'develop' into ekcoh/rebinding-issues-events
ekcoh Jun 25, 2025
abcfe77
Added timeout to example to make sure a user do not get stuck, if e.g…
ekcoh Jun 25, 2025
cbdbe1c
Merge branch 'ekcoh/rebinding-issues-events' of github.com:Unity-Tech…
ekcoh Jun 25, 2025
b21c51a
Version bump to 1.15.0
ekcoh Jun 25, 2025
7b1a080
Version bump generated files
ekcoh Jun 25, 2025
332e90b
Fixed xmldoc referencing internal types.
ekcoh Jun 26, 2025
216d7fe
Merge branch 'develop' into ekcoh/rebinding-issues-events
ekcoh Jun 26, 2025
538127f
Added support for suppressing any kind of state event during rebindin…
ekcoh Jun 26, 2025
1f0514c
Merge branch 'ekcoh/rebinding-issues-events' of github.com:Unity-Tech…
ekcoh Jun 26, 2025
b5272cd
Added missing namespace to RebindSaveLoad
ekcoh Jun 26, 2025
1ba9dba
Temporarily disabled new function of suppressing non-matched input, i…
ekcoh Jun 26, 2025
7885737
Added ability to also reset all bindings
ekcoh Jun 26, 2025
baf6180
Tweaked UI to also render correctly on 16:10, e.g. WebGL
ekcoh Jun 26, 2025
980abc0
Fixed a bug where selection wouldn't be restored if cancelling rebind…
ekcoh Jun 26, 2025
c7693dc
Added proper pausing to reveal any issues tied to time scale being ze…
ekcoh Jun 26, 2025
fa1eada
Unsaved changes
ekcoh Jun 26, 2025
cabce4f
Fixed xmldoc comment
ekcoh Jun 27, 2025
b6ec069
Replaced pointless interaction with a mini game which in turn surface…
ekcoh Jun 28, 2025
cf4a2b2
FIX: Bug fix to RebindActionUI not showing binding when no event occurrs
ekcoh Jun 30, 2025
a82be70
Sample cleanup
ekcoh Jun 30, 2025
b78ae23
Sample cleanup
ekcoh Jun 30, 2025
bdd16a4
Extracted input system related logic from Player into PlayerControlle…
ekcoh Jun 30, 2025
414d7a6
Rumble and light effect fix for sample
ekcoh Jun 30, 2025
b2a111d
Fixed issues with light and rumble effects, removed unused file, remo…
ekcoh Jul 1, 2025
e7e99a3
Added missing player explosion, removed unused material, fixed derive…
ekcoh Jul 1, 2025
2c3fdca
Separated FeedbackController out of PlayerController to support rumbl…
ekcoh Jul 1, 2025
b1bf5d3
Code cleanup and simplifications
ekcoh Jul 1, 2025
f934a06
Fix: Rebinding gamepad icons fail for derived (implicitly converted) …
ekcoh Jul 1, 2025
c534b22
Removed debug logs
ekcoh Jul 2, 2025
0a25ec2
Eliminated chance of nullptr exception from CanvasGroupModifier which…
ekcoh Jul 2, 2025
d367d9c
Improved code quality of InvokeUnityEvents added corresponding editor…
ekcoh Jul 2, 2025
c7483d3
Fix: Prevent exiting into game when being 2 levels down menu hierarchy
ekcoh Jul 2, 2025
4cac584
Added bug case references
ekcoh Jul 2, 2025
fd7f756
Replaced incorrect Transform with RectTransform to support free aspec…
ekcoh Jul 2, 2025
ac8dd32
FIX: ISXB-1595 Fixed an issue that could cause actions, e.g. UI defau…
ekcoh Jul 2, 2025
a99725c
Merge branch 'develop' into ekcoh/rebinding-issues-events
ekcoh Jul 2, 2025
5c9beaf
Removed redundant Image components from rebinding sample.
ekcoh Jul 2, 2025
d4a6e43
Code cleanup
ekcoh Jul 2, 2025
c320b4a
Merge branch 'ekcoh/rebinding-issues-events' of github.com:Unity-Tech…
ekcoh Jul 2, 2025
f53427a
Updated rebinding asset based on changes from develop
ekcoh Jul 2, 2025
e78eae1
Fixed an issue where projectiles where destroyed at a fixed distance …
ekcoh Jul 2, 2025
c6e4018
Fixed a numerical error in FeedbackController and simplified associat…
ekcoh Jul 2, 2025
6780d58
Renamed assets to have more meaningful names, created a dedicated UI …
ekcoh Jul 2, 2025
96508f6
Undo addition of suppress non-matching events feature since its not r…
ekcoh Jul 2, 2025
86a1a35
Decreased rebinding timeout to 6 seconds
ekcoh Jul 3, 2025
8816429
Fix: Improved the fix to the main issue that this branch addresses so…
ekcoh Jul 3, 2025
53104a1
Removed unused properties and added sensitivity constants that can la…
ekcoh Jul 3, 2025
43829da
Fixed typo "something"
ekcoh Jul 3, 2025
5d40eb4
Made a setting to enable/disable UI actions during gameplay. It defau…
ekcoh Jul 3, 2025
9e5c31c
Code cleanup and simplification after reviewing all code on the branch
ekcoh Jul 3, 2025
29414a5
Added #ifdef to handle rigidbodys different between Unity 6 and older…
ekcoh Jul 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Assets/Samples/InGameHints/InGameHintsActions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was auto-generated by com.unity.inputsystem:InputActionCodeGenerator
// version 1.14.1
// version 1.15.0
// from Assets/Samples/InGameHints/InGameHintsActions.inputactions
//
// Changes to this file may cause incorrect behavior and will be lost if
Expand Down
161 changes: 161 additions & 0 deletions Assets/Samples/RebindingUI/ActionLabel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
using System;
using System.Collections.Generic;
using UnityEngine.Events;
using UnityEngine.UI;

namespace UnityEngine.InputSystem.Samples.RebindUI
{
public class ActionLabel : MonoBehaviour
{
[Tooltip("Reference to action that is to be rebound from the UI.")]
[SerializeField]
private InputActionReference m_Action;

[SerializeField]
private string m_BindingId;

[SerializeField]
private InputBinding.DisplayStringOptions m_DisplayStringOptions;

[Tooltip("Text label that will receive the current, formatted binding string.")]
[SerializeField]
private Text m_BindingText;

[Tooltip("Event that is triggered when the way the binding is display should be updated. This allows displaying "
+ "bindings in custom ways, e.g. using images instead of text.")]
[SerializeField]
private UpdateBindingUIEvent m_UpdateBindingUIEvent;

private static List<ActionLabel> s_InputActionUIs;

/// <summary>
/// Reference to the action that is to be rebound.
/// </summary>
public InputActionReference actionReference
{
get => m_Action;
set
{
m_Action = value;
UpdateBindingDisplay();
}
}

/// <summary>
/// ID (in string form) of the binding that is to be rebound on the action.
/// </summary>
/// <seealso cref="InputBinding.id"/>
public string bindingId
{
get => m_BindingId;
set
{
m_BindingId = value;
UpdateBindingDisplay();
}
}

/// <summary>
/// Text component that receives the display string of the binding. Can be <c>null</c> in which
/// case the component entirely relies on <see cref="updateBindingUIEvent"/>.
/// </summary>
public Text bindingText
{
get => m_BindingText;
set
{
m_BindingText = value;
UpdateBindingDisplay();
}
}

/// <summary>
/// Display options for the binding.
/// </summary>
public InputBinding.DisplayStringOptions displayStringOptions
{
get => m_DisplayStringOptions;
set
{
m_DisplayStringOptions = value;
UpdateBindingDisplay();
}
}

/// <summary>
/// Trigger a refresh of the currently displayed binding.
/// </summary>
public void UpdateBindingDisplay()
{
var displayString = string.Empty;
var deviceLayoutName = default(string);
var controlPath = default(string);

// Get display string from action.
var action = m_Action?.action;
if (action != null)
{
var bindingIndex = action.bindings.IndexOf(x => x.id.ToString() == m_BindingId);
if (bindingIndex != -1)
displayString = action.GetBindingDisplayString(bindingIndex, out deviceLayoutName, out controlPath, displayStringOptions);
}

// Set on label (if any).
if (m_BindingText != null)
m_BindingText.text = displayString;

// Give listeners a chance to configure UI in response.
m_UpdateBindingUIEvent?.Invoke(this, displayString, deviceLayoutName, controlPath);
}

protected void OnEnable()
{
if (s_InputActionUIs == null)
s_InputActionUIs = new List<ActionLabel>();
s_InputActionUIs.Add(this);
if (s_InputActionUIs.Count == 1)
InputSystem.onActionChange += OnActionChange;
UpdateBindingDisplay();
}

protected void OnDisable()
{
s_InputActionUIs.Remove(this);
if (s_InputActionUIs.Count == 0)
{
s_InputActionUIs = null;
InputSystem.onActionChange -= OnActionChange;
}
}

// When the action system re-resolves bindings, we want to update our UI in response
// to show the currently relevant binding.
private static void OnActionChange(object obj, InputActionChange change)
{
if (change != InputActionChange.BoundControlsChanged)
return;

var action = obj as InputAction;
var actionMap = action?.actionMap ?? obj as InputActionMap;
var actionAsset = actionMap?.asset ?? obj as InputActionAsset;

for (var i = 0; i < s_InputActionUIs.Count; ++i)
{
var component = s_InputActionUIs[i];
var referencedAction = component.actionReference?.action;
if (referencedAction == null)
continue;

if (referencedAction == action ||
referencedAction.actionMap == actionMap ||
referencedAction.actionMap?.asset == actionAsset)
component.UpdateBindingDisplay();
}
}
}

[Serializable]
public class UpdateBindingUIEvent : UnityEvent<ActionLabel, string, string, string>
{
}
}
2 changes: 2 additions & 0 deletions Assets/Samples/RebindingUI/ActionLabel.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

162 changes: 162 additions & 0 deletions Assets/Samples/RebindingUI/ActionLabelEditor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#if UNITY_EDITOR
using System.Linq;
using UnityEditor;

////TODO: support multi-object editing

namespace UnityEngine.InputSystem.Samples.RebindUI
{
/// <summary>
/// A custom inspector for <see cref="RebindActionUI"/> which provides a more convenient way for
/// picking the binding which to rebind.
/// </summary>
[CustomEditor(typeof(ActionLabel))]
public class ActionLabelEditor : UnityEditor.Editor
{
protected void OnEnable()
{
m_ActionProperty = serializedObject.FindProperty("m_Action");
m_BindingIdProperty = serializedObject.FindProperty("m_BindingId");
m_BindingTextProperty = serializedObject.FindProperty("m_BindingText");
m_DisplayStringOptionsProperty = serializedObject.FindProperty("m_DisplayStringOptions");
m_UpdateBindingUIEventProperty = serializedObject.FindProperty("m_UpdateBindingUIEvent");

RefreshBindingOptions();
}

public override void OnInspectorGUI()
{
EditorGUI.BeginChangeCheck();

// Binding section.
EditorGUILayout.LabelField(m_BindingLabel, Styles.boldLabel);
using (new EditorGUI.IndentLevelScope())
{
EditorGUILayout.PropertyField(m_ActionProperty);

var newSelectedBinding = EditorGUILayout.Popup(m_BindingLabel, m_SelectedBindingOption, m_BindingOptions);
if (newSelectedBinding != m_SelectedBindingOption)
{
var bindingId = m_BindingOptionValues[newSelectedBinding];
m_BindingIdProperty.stringValue = bindingId;
m_SelectedBindingOption = newSelectedBinding;
}

var optionsOld = (InputBinding.DisplayStringOptions)m_DisplayStringOptionsProperty.intValue;
var optionsNew = (InputBinding.DisplayStringOptions)EditorGUILayout.EnumFlagsField(m_DisplayOptionsLabel, optionsOld);
if (optionsOld != optionsNew)
m_DisplayStringOptionsProperty.intValue = (int)optionsNew;
}

// UI section.
EditorGUILayout.Space();
EditorGUILayout.LabelField(m_UILabel, Styles.boldLabel);
using (new EditorGUI.IndentLevelScope())
{
EditorGUILayout.PropertyField(m_BindingTextProperty);
}

// Events section.
EditorGUILayout.Space();
EditorGUILayout.LabelField(m_EventsLabel, Styles.boldLabel);
using (new EditorGUI.IndentLevelScope())
{
EditorGUILayout.PropertyField(m_UpdateBindingUIEventProperty);
}

if (EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
RefreshBindingOptions();
}
}

protected void RefreshBindingOptions()
{
var actionReference = (InputActionReference)m_ActionProperty.objectReferenceValue;
var action = actionReference?.action;

if (action == null)
{
m_BindingOptions = new GUIContent[0];
m_BindingOptionValues = new string[0];
m_SelectedBindingOption = -1;
return;
}

var bindings = action.bindings;
var bindingCount = bindings.Count;

m_BindingOptions = new GUIContent[bindingCount];
m_BindingOptionValues = new string[bindingCount];
m_SelectedBindingOption = -1;

var currentBindingId = m_BindingIdProperty.stringValue;
for (var i = 0; i < bindingCount; ++i)
{
var binding = bindings[i];
var bindingId = binding.id.ToString();
var haveBindingGroups = !string.IsNullOrEmpty(binding.groups);

// If we don't have a binding groups (control schemes), show the device that if there are, for example,
// there are two bindings with the display string "A", the user can see that one is for the keyboard
// and the other for the gamepad.
var displayOptions =
InputBinding.DisplayStringOptions.DontUseShortDisplayNames | InputBinding.DisplayStringOptions.IgnoreBindingOverrides;
if (!haveBindingGroups)
displayOptions |= InputBinding.DisplayStringOptions.DontOmitDevice;

// Create display string.
var displayString = action.GetBindingDisplayString(i, displayOptions);

// If binding is part of a composite, include the part name.
if (binding.isPartOfComposite)
displayString = $"{ObjectNames.NicifyVariableName(binding.name)}: {displayString}";

// Some composites use '/' as a separator. When used in popup, this will lead to to submenus. Prevent
// by instead using a backlash.
displayString = displayString.Replace('/', '\\');

// If the binding is part of control schemes, mention them.
if (haveBindingGroups)
{
var asset = action.actionMap?.asset;
if (asset != null)
{
var controlSchemes = string.Join(", ",
binding.groups.Split(InputBinding.Separator)
.Select(x => asset.controlSchemes.FirstOrDefault(c => c.bindingGroup == x).name));

displayString = $"{displayString} ({controlSchemes})";
}
}

m_BindingOptions[i] = new GUIContent(displayString);
m_BindingOptionValues[i] = bindingId;

if (currentBindingId == bindingId)
m_SelectedBindingOption = i;
}
}

private SerializedProperty m_ActionProperty;
private SerializedProperty m_BindingIdProperty;
private SerializedProperty m_BindingTextProperty;
private SerializedProperty m_UpdateBindingUIEventProperty;
private SerializedProperty m_DisplayStringOptionsProperty;

private GUIContent m_BindingLabel = new GUIContent("Binding");
private GUIContent m_DisplayOptionsLabel = new GUIContent("Display Options");
private GUIContent m_UILabel = new GUIContent("UI");
private GUIContent m_EventsLabel = new GUIContent("Events");
private GUIContent[] m_BindingOptions;
private string[] m_BindingOptionValues;
private int m_SelectedBindingOption;

private static class Styles
{
public static GUIStyle boldLabel = new GUIStyle("MiniBoldLabel");
}
}
}
#endif
2 changes: 2 additions & 0 deletions Assets/Samples/RebindingUI/ActionLabelEditor.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 51 additions & 0 deletions Assets/Samples/RebindingUI/CanvasGroupModifier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using UnityEngine.EventSystems;

namespace UnityEngine.InputSystem.Samples.RebindUI
{
/// <summary>
/// Simple utility that modifies a referenced CanvasGroup while being active.
/// </summary>
public class CanvasGroupModifier : MonoBehaviour
{
[Tooltip("The Canvas Group to be modified while this component is active")]
public CanvasGroup canvasGroup;

[Tooltip("The interactable setting to use for the Canvas Group while this component is active")]
public bool interactable = false;

private bool m_SavedInteractable;
private GameObject m_SelectedObject;

private void OnEnable()
{
if (canvasGroup != null)
{
// Store selection to make sure it is not changed when switching "windows".
m_SelectedObject = EventSystem.current.currentSelectedGameObject;

// Save current setting and override
m_SavedInteractable = canvasGroup.interactable;
canvasGroup.interactable = interactable;
}
}

private void OnDisable()
{
if (canvasGroup != null)
{
// Restore previous setting.
canvasGroup.interactable = m_SavedInteractable;

// Restore previous selection.
var eventSystem = EventSystem.current;
if (eventSystem != null)
{
if (m_SelectedObject != null)
eventSystem.SetSelectedGameObject(m_SelectedObject);
else if (EventSystem.current.currentSelectedGameObject == null)
eventSystem.SetSelectedGameObject(eventSystem.firstSelectedGameObject);
}
}
}
}
}
2 changes: 2 additions & 0 deletions Assets/Samples/RebindingUI/CanvasGroupModifier.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading