From cd6c4f36c16e321e6161149b9e151b21c53d59fe Mon Sep 17 00:00:00 2001
From: "ALIENJACK\\alien" <alienjack@foxmail.com>
Date: Thu, 21 Nov 2024 20:32:41 +0800
Subject: [PATCH] =?UTF-8?q?UI=E8=BE=93=E5=85=A5=E7=B3=BB=E7=BB=9F=E5=B7=B2?=
 =?UTF-8?q?=E6=8E=A5=E5=85=A5InputSystem?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../Assets/Resources/InputSystem.meta         |   8 +
 .../InputSystem/UI_InputSetting.inputactions  | 304 ++++++++++++++++++
 .../UI_InputSetting.inputactions.meta         |  14 +
 .../Assets/Scene/AxibugEmuOnline.Client.unity | 127 +++++++-
 .../Script/AxibugEmuOnline.Client.asmdef      |   3 +-
 .../Script/ControlSchemes/ControlScheme.cs    |  65 ----
 .../Script/ControlSchemes/NesGamingScheme.cs  |  27 --
 .../Script/ControlSchemes/NormalScheme.cs     |  18 --
 ...rolSchemes.meta => IkeyMapperChanger.meta} |   0
 .../IkeyMapperChanger/CommandChanger.cs       |  12 +
 .../CommandChanger.cs.meta}                   |   0
 .../Script/IkeyMapperChanger/GamingChanger.cs |  10 +
 .../GamingChanger.cs.meta}                    |   2 +-
 .../Script/IkeyMapperChanger/Legacy.meta      |   8 +
 .../Legacy/GamingChanger_Legacy.cs            |  25 ++
 .../Legacy/GamingChanger_Legacy.cs.meta}      |   2 +-
 .../Legacy/NormalChanger_Legacy.cs            |  58 ++++
 .../Legacy/NormalChanger_Legacy.cs.meta       |  11 +
 .../Script/IkeyMapperChanger/NormalChanger.cs |  10 +
 .../IkeyMapperChanger/NormalChanger.cs.meta   |  11 +
 .../Assets/Script/Manager/AppEmu.cs           |   2 +-
 .../Assets/Script/NesEmulator/NesEmulator.cs  |   2 +-
 .../UI/CommandDispatcher/CommandDispatcher.cs |  72 +++--
 .../UI/CommandDispatcher/CommandListener.cs   |  65 ++++
 .../CommandDispatcher/CommandListener.cs.meta |  11 +
 .../CommandListener_Legacy.cs                 |  38 +++
 .../CommandListener_Legacy.cs.meta            |  11 +
 .../UI/CommandDispatcher/ICommandListener.cs  |  24 ++
 .../ICommandListener.cs.meta                  |  11 +
 .../Assets/Script/UI/InGameUI/InGameUI.cs     |   2 +-
 .../Assets/Script/UI/LaunchUI.cs              |   2 +-
 .../Assets/Script/UI/OptionUI/OptionUI.cs     |   8 +-
 .../ProjectSettings/ProjectSettings.asset     |   2 +-
 .../ProjectSettings/TagManager.asset          |   3 +-
 34 files changed, 805 insertions(+), 163 deletions(-)
 create mode 100644 AxibugEmuOnline.Client/Assets/Resources/InputSystem.meta
 create mode 100644 AxibugEmuOnline.Client/Assets/Resources/InputSystem/UI_InputSetting.inputactions
 create mode 100644 AxibugEmuOnline.Client/Assets/Resources/InputSystem/UI_InputSetting.inputactions.meta
 delete mode 100644 AxibugEmuOnline.Client/Assets/Script/ControlSchemes/ControlScheme.cs
 delete mode 100644 AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NesGamingScheme.cs
 delete mode 100644 AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NormalScheme.cs
 rename AxibugEmuOnline.Client/Assets/Script/{ControlSchemes.meta => IkeyMapperChanger.meta} (100%)
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/CommandChanger.cs
 rename AxibugEmuOnline.Client/Assets/Script/{ControlSchemes/ControlScheme.cs.meta => IkeyMapperChanger/CommandChanger.cs.meta} (100%)
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/GamingChanger.cs
 rename AxibugEmuOnline.Client/Assets/Script/{ControlSchemes/NormalScheme.cs.meta => IkeyMapperChanger/GamingChanger.cs.meta} (83%)
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy.meta
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/GamingChanger_Legacy.cs
 rename AxibugEmuOnline.Client/Assets/Script/{ControlSchemes/NesGamingScheme.cs.meta => IkeyMapperChanger/Legacy/GamingChanger_Legacy.cs.meta} (83%)
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/NormalChanger_Legacy.cs
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/NormalChanger_Legacy.cs.meta
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/NormalChanger.cs
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/NormalChanger.cs.meta
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener.cs
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener.cs.meta
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener_Legacy.cs
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener_Legacy.cs.meta
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/ICommandListener.cs
 create mode 100644 AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/ICommandListener.cs.meta

diff --git a/AxibugEmuOnline.Client/Assets/Resources/InputSystem.meta b/AxibugEmuOnline.Client/Assets/Resources/InputSystem.meta
new file mode 100644
index 00000000..38637690
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Resources/InputSystem.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 6178d336be6488b46aed623405e79f7b
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/AxibugEmuOnline.Client/Assets/Resources/InputSystem/UI_InputSetting.inputactions b/AxibugEmuOnline.Client/Assets/Resources/InputSystem/UI_InputSetting.inputactions
new file mode 100644
index 00000000..5b0afe02
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Resources/InputSystem/UI_InputSetting.inputactions
@@ -0,0 +1,304 @@
+{
+    "name": "New Controls",
+    "maps": [
+        {
+            "name": "UI_Normal",
+            "id": "9a397a4f-4d88-492f-a918-bf9b8d3be756",
+            "actions": [
+                {
+                    "name": "SelectItemLeft",
+                    "type": "Button",
+                    "id": "107019fe-240c-46ff-8c62-cb385ef8b9af",
+                    "expectedControlType": "Button",
+                    "processors": "",
+                    "interactions": "",
+                    "initialStateCheck": false
+                },
+                {
+                    "name": "SelectItemRight",
+                    "type": "Button",
+                    "id": "826dd3f1-2cf8-4169-97c8-dfb56b850143",
+                    "expectedControlType": "Button",
+                    "processors": "",
+                    "interactions": "",
+                    "initialStateCheck": false
+                },
+                {
+                    "name": "SelectItemUp",
+                    "type": "Button",
+                    "id": "505dabb4-91f7-430c-8696-092690269639",
+                    "expectedControlType": "Button",
+                    "processors": "",
+                    "interactions": "",
+                    "initialStateCheck": false
+                },
+                {
+                    "name": "SelectItemDown",
+                    "type": "Button",
+                    "id": "b3da8633-7f50-44b3-8302-50706e589307",
+                    "expectedControlType": "Button",
+                    "processors": "",
+                    "interactions": "",
+                    "initialStateCheck": false
+                },
+                {
+                    "name": "Enter",
+                    "type": "Button",
+                    "id": "0bdf3154-e1db-4044-af50-cacb3764a07c",
+                    "expectedControlType": "Button",
+                    "processors": "",
+                    "interactions": "",
+                    "initialStateCheck": false
+                },
+                {
+                    "name": "Back",
+                    "type": "Button",
+                    "id": "68074d67-61a1-4a4d-bd68-8398b0e7afe3",
+                    "expectedControlType": "Button",
+                    "processors": "",
+                    "interactions": "",
+                    "initialStateCheck": false
+                },
+                {
+                    "name": "OptionMenu",
+                    "type": "Button",
+                    "id": "64b67280-c530-4e38-b3ff-8d0177591396",
+                    "expectedControlType": "Button",
+                    "processors": "",
+                    "interactions": "",
+                    "initialStateCheck": false
+                }
+            ],
+            "bindings": [
+                {
+                    "name": "",
+                    "id": "fc724bf2-7736-419c-9f46-19bd45a0d276",
+                    "path": "<Keyboard>/a",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "SelectItemLeft",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "02f4433e-4417-4fef-b178-a616e2941311",
+                    "path": "<Keyboard>/leftArrow",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "SelectItemLeft",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "cb874e72-d3db-4024-b9fb-37190acd9568",
+                    "path": "<Keyboard>/d",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "SelectItemRight",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "646b923b-4d3d-4b5c-9dd2-0119e9d3e2c5",
+                    "path": "<Keyboard>/rightArrow",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "SelectItemRight",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "28fa0139-d5a2-4e26-87af-2043e01234e6",
+                    "path": "<Keyboard>/w",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "SelectItemUp",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "4474efdf-70ff-4826-883c-2fdf9f96e78e",
+                    "path": "<Keyboard>/upArrow",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "SelectItemUp",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "392a8cbc-71f6-4282-b945-4c7b3d17ba3a",
+                    "path": "<Keyboard>/s",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "SelectItemDown",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "f30b6fb3-147e-4997-b628-fab3f635192b",
+                    "path": "<Keyboard>/downArrow",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "SelectItemDown",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "70c6db12-432b-482d-99a1-71e002c30157",
+                    "path": "<Keyboard>/k",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "Enter",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "48d5c450-6ac3-40fb-8ff4-66c7f3b3a00b",
+                    "path": "<Keyboard>/enter",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "Enter",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "ef83ae7c-a809-4f23-a206-102199a5ede3",
+                    "path": "<Keyboard>/l",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "Back",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "14b503c8-80a1-458c-9e0f-a3fa38f314be",
+                    "path": "<Keyboard>/backspace",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "Back",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "e1e12f45-fb41-4b78-adbf-add2881bd4b1",
+                    "path": "<Keyboard>/i",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "OptionMenu",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                },
+                {
+                    "name": "",
+                    "id": "0b010e17-3581-42e6-90b1-f1bf728a3a0c",
+                    "path": "<Keyboard>/shift",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "OptionMenu",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                }
+            ]
+        },
+        {
+            "name": "UI_InGame",
+            "id": "2c8af03e-03e7-4553-81c6-dcff543cdcdc",
+            "actions": [
+                {
+                    "name": "OptionMenu",
+                    "type": "Button",
+                    "id": "cab3c346-07e2-4c0c-8377-cb934dd28bd3",
+                    "expectedControlType": "Button",
+                    "processors": "",
+                    "interactions": "",
+                    "initialStateCheck": false
+                }
+            ],
+            "bindings": [
+                {
+                    "name": "",
+                    "id": "28d4d045-1070-4ea0-be35-b5ffb1c33bcb",
+                    "path": "<Keyboard>/escape",
+                    "interactions": "",
+                    "processors": "",
+                    "groups": "Keyboard",
+                    "action": "OptionMenu",
+                    "isComposite": false,
+                    "isPartOfComposite": false
+                }
+            ]
+        }
+    ],
+    "controlSchemes": [
+        {
+            "name": "Keyboard",
+            "bindingGroup": "Keyboard",
+            "devices": [
+                {
+                    "devicePath": "<Keyboard>",
+                    "isOptional": false,
+                    "isOR": false
+                }
+            ]
+        },
+        {
+            "name": "UniversalGamePad",
+            "bindingGroup": "UniversalGamePad",
+            "devices": [
+                {
+                    "devicePath": "<Gamepad>",
+                    "isOptional": false,
+                    "isOR": false
+                }
+            ]
+        },
+        {
+            "name": "Xbox Controller",
+            "bindingGroup": "Xbox Controller",
+            "devices": [
+                {
+                    "devicePath": "<XInputController>",
+                    "isOptional": false,
+                    "isOR": false
+                }
+            ]
+        },
+        {
+            "name": "PlayStation Controller",
+            "bindingGroup": "PlayStation Controller",
+            "devices": [
+                {
+                    "devicePath": "<DualShockGamepad>",
+                    "isOptional": false,
+                    "isOR": false
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/AxibugEmuOnline.Client/Assets/Resources/InputSystem/UI_InputSetting.inputactions.meta b/AxibugEmuOnline.Client/Assets/Resources/InputSystem/UI_InputSetting.inputactions.meta
new file mode 100644
index 00000000..e9c5b5a9
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Resources/InputSystem/UI_InputSetting.inputactions.meta
@@ -0,0 +1,14 @@
+fileFormatVersion: 2
+guid: eb413fd14a8483440af9652b7e4df5e1
+ScriptedImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 2
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
+  script: {fileID: 11500000, guid: 8404be70184654265930450def6a9037, type: 3}
+  generateWrapperCode: 0
+  wrapperCodePath: 
+  wrapperClassName: 
+  wrapperCodeNamespace: InputSystem
diff --git a/AxibugEmuOnline.Client/Assets/Scene/AxibugEmuOnline.Client.unity b/AxibugEmuOnline.Client/Assets/Scene/AxibugEmuOnline.Client.unity
index 58b4ad59..f587967d 100644
--- a/AxibugEmuOnline.Client/Assets/Scene/AxibugEmuOnline.Client.unity
+++ b/AxibugEmuOnline.Client/Assets/Scene/AxibugEmuOnline.Client.unity
@@ -150,16 +150,25 @@ MonoBehaviour:
   m_GameObject: {fileID: 74796456}
   m_Enabled: 1
   m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
+  m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3}
   m_Name: 
   m_EditorClassIdentifier: 
-  m_HorizontalAxis: Horizontal
-  m_VerticalAxis: Vertical
-  m_SubmitButton: Submit
-  m_CancelButton: Cancel
-  m_InputActionsPerSecond: 10
-  m_RepeatDelay: 0.5
-  m_ForceModuleActive: 0
+  m_MoveRepeatDelay: 0.5
+  m_MoveRepeatRate: 0.1
+  m_XRTrackingOrigin: {fileID: 0}
+  m_ActionsAsset: {fileID: -944628639613478452, guid: eb413fd14a8483440af9652b7e4df5e1, type: 3}
+  m_PointAction: {fileID: 0}
+  m_MoveAction: {fileID: 0}
+  m_SubmitAction: {fileID: 0}
+  m_CancelAction: {fileID: 0}
+  m_LeftClickAction: {fileID: 0}
+  m_MiddleClickAction: {fileID: 0}
+  m_RightClickAction: {fileID: 0}
+  m_ScrollWheelAction: {fileID: 0}
+  m_TrackedDevicePositionAction: {fileID: 0}
+  m_TrackedDeviceOrientationAction: {fileID: 0}
+  m_DeselectOnBackgroundClick: 1
+  m_PointerBehavior: 0
 --- !u!114 &74796458
 MonoBehaviour:
   m_ObjectHideFlags: 0
@@ -2499,7 +2508,7 @@ PrefabInstance:
       objectReference: {fileID: 0}
     - target: {fileID: 1639091784002085428, guid: 450328d5a907c8249a60bc3980ba66f6, type: 3}
       propertyPath: m_RootOrder
-      value: 0
+      value: 1
       objectReference: {fileID: 0}
     - target: {fileID: 1639091784002085428, guid: 450328d5a907c8249a60bc3980ba66f6, type: 3}
       propertyPath: m_AnchorMax.x
@@ -13565,6 +13574,7 @@ RectTransform:
   m_LocalPosition: {x: 0, y: 0, z: 0}
   m_LocalScale: {x: 0, y: 0, z: 0}
   m_Children:
+  - {fileID: 2073453794}
   - {fileID: 1983793178}
   - {fileID: 246947326}
   - {fileID: 1318590597}
@@ -13665,6 +13675,99 @@ RectTransform:
   m_CorrespondingSourceObject: {fileID: 1639091784002085428, guid: 450328d5a907c8249a60bc3980ba66f6, type: 3}
   m_PrefabInstance: {fileID: 730698711}
   m_PrefabAsset: {fileID: 0}
+--- !u!1 &2073453793
+GameObject:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  serializedVersion: 6
+  m_Component:
+  - component: {fileID: 2073453794}
+  - component: {fileID: 2073453795}
+  m_Layer: 0
+  m_Name: UI_Input
+  m_TagString: UIInput
+  m_Icon: {fileID: 0}
+  m_NavMeshLayer: 0
+  m_StaticEditorFlags: 0
+  m_IsActive: 1
+--- !u!4 &2073453794
+Transform:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2073453793}
+  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
+  m_LocalPosition: {x: 0, y: 0, z: -10799.999}
+  m_LocalScale: {x: 108, y: 108, z: 108}
+  m_Children: []
+  m_Father: {fileID: 1599240741}
+  m_RootOrder: 0
+  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!114 &2073453795
+MonoBehaviour:
+  m_ObjectHideFlags: 0
+  m_CorrespondingSourceObject: {fileID: 0}
+  m_PrefabInstance: {fileID: 0}
+  m_PrefabAsset: {fileID: 0}
+  m_GameObject: {fileID: 2073453793}
+  m_Enabled: 1
+  m_EditorHideFlags: 0
+  m_Script: {fileID: 11500000, guid: 62899f850307741f2a39c98a8b639597, type: 3}
+  m_Name: 
+  m_EditorClassIdentifier: 
+  m_Actions: {fileID: -944628639613478452, guid: eb413fd14a8483440af9652b7e4df5e1, type: 3}
+  m_NotificationBehavior: 3
+  m_UIInputModule: {fileID: 74796457}
+  m_DeviceLostEvent:
+    m_PersistentCalls:
+      m_Calls: []
+  m_DeviceRegainedEvent:
+    m_PersistentCalls:
+      m_Calls: []
+  m_ControlsChangedEvent:
+    m_PersistentCalls:
+      m_Calls: []
+  m_ActionEvents:
+  - m_PersistentCalls:
+      m_Calls: []
+    m_ActionId: 107019fe-240c-46ff-8c62-cb385ef8b9af
+    m_ActionName: UI_Normal/SelectItemLeft
+  - m_PersistentCalls:
+      m_Calls: []
+    m_ActionId: 826dd3f1-2cf8-4169-97c8-dfb56b850143
+    m_ActionName: UI_Normal/SelectItemRight
+  - m_PersistentCalls:
+      m_Calls: []
+    m_ActionId: 505dabb4-91f7-430c-8696-092690269639
+    m_ActionName: UI_Normal/SelectItemUp
+  - m_PersistentCalls:
+      m_Calls: []
+    m_ActionId: b3da8633-7f50-44b3-8302-50706e589307
+    m_ActionName: UI_Normal/SelectItemDown
+  - m_PersistentCalls:
+      m_Calls: []
+    m_ActionId: 0bdf3154-e1db-4044-af50-cacb3764a07c
+    m_ActionName: UI_Normal/Enter
+  - m_PersistentCalls:
+      m_Calls: []
+    m_ActionId: 68074d67-61a1-4a4d-bd68-8398b0e7afe3
+    m_ActionName: UI_Normal/Back
+  - m_PersistentCalls:
+      m_Calls: []
+    m_ActionId: 64b67280-c530-4e38-b3ff-8d0177591396
+    m_ActionName: UI_Normal/OptionMenu
+  - m_PersistentCalls:
+      m_Calls: []
+    m_ActionId: cab3c346-07e2-4c0c-8377-cb934dd28bd3
+    m_ActionName: UI_InGame/OptionMenu
+  m_NeverAutoSwitchControlSchemes: 0
+  m_DefaultControlScheme: Keyboard
+  m_DefaultActionMap: UI_Normal
+  m_SplitScreenIndex: -1
+  m_Camera: {fileID: 0}
 --- !u!1001 &1963501580473600373
 PrefabInstance:
   m_ObjectHideFlags: 0
@@ -13682,7 +13785,7 @@ PrefabInstance:
       objectReference: {fileID: 0}
     - target: {fileID: 1963501579241001456, guid: 334eee9f85f308347844f8f5e99167c3, type: 3}
       propertyPath: m_RootOrder
-      value: 2
+      value: 3
       objectReference: {fileID: 0}
     - target: {fileID: 1963501579241001456, guid: 334eee9f85f308347844f8f5e99167c3, type: 3}
       propertyPath: m_AnchorMax.x
@@ -13791,7 +13894,7 @@ PrefabInstance:
       objectReference: {fileID: 0}
     - target: {fileID: 3531919739338806919, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
       propertyPath: m_RootOrder
-      value: 3
+      value: 4
       objectReference: {fileID: 0}
     - target: {fileID: 3531919739338806919, guid: 1de15a80c8c1aa94486563740a15d91c, type: 3}
       propertyPath: m_AnchorMax.x
@@ -13944,7 +14047,7 @@ PrefabInstance:
       objectReference: {fileID: 0}
     - target: {fileID: 4478785627166277610, guid: d3c2508a55398a24db5d68f68d2702ea, type: 3}
       propertyPath: m_RootOrder
-      value: 1
+      value: 2
       objectReference: {fileID: 0}
     - target: {fileID: 4478785627166277610, guid: d3c2508a55398a24db5d68f68d2702ea, type: 3}
       propertyPath: m_AnchorMax.x
diff --git a/AxibugEmuOnline.Client/Assets/Script/AxibugEmuOnline.Client.asmdef b/AxibugEmuOnline.Client/Assets/Script/AxibugEmuOnline.Client.asmdef
index 410a9f7f..177a08c9 100644
--- a/AxibugEmuOnline.Client/Assets/Script/AxibugEmuOnline.Client.asmdef
+++ b/AxibugEmuOnline.Client/Assets/Script/AxibugEmuOnline.Client.asmdef
@@ -4,7 +4,8 @@
     "references": [
         "GUID:390a2c4058e5c304a87e8be70c84d80b",
         "GUID:085dc26d74e6f994a924d401ea41a5a8",
-        "GUID:0a45db2096af23647aaafe5b70ccb4d7"
+        "GUID:0a45db2096af23647aaafe5b70ccb4d7",
+        "GUID:75469ad4d38634e559750d17036d5f7c"
     ],
     "includePlatforms": [],
     "excludePlatforms": [],
diff --git a/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/ControlScheme.cs b/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/ControlScheme.cs
deleted file mode 100644
index 957a0e1e..00000000
--- a/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/ControlScheme.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System.Collections.Generic;
-using UnityEngine;
-
-namespace AxibugEmuOnline.Client
-{
-    public abstract class ControlScheme
-    {
-        private static ControlScheme m_current;
-        public static ControlScheme Current
-        {
-            get => m_current;
-            set
-            {
-                m_current = value;
-
-                Dictionary<KeyCode, EnumCommand> mapper = new Dictionary<KeyCode, EnumCommand>();
-                m_current.SetUIKeys(mapper);
-                CommandDispatcher.Instance.SetKeyMapper(mapper);
-            }
-        }
-
-        public string Name { get; private set; }
-
-        public virtual void SetUIKeys(Dictionary<KeyCode, EnumCommand> uiKeyMapper)
-        {
-            uiKeyMapper[KeyCode.A] = EnumCommand.SelectItemLeft;
-            uiKeyMapper[KeyCode.D] = EnumCommand.SelectItemRight;
-            uiKeyMapper[KeyCode.W] = EnumCommand.SelectItemUp;
-            uiKeyMapper[KeyCode.S] = EnumCommand.SelectItemDown;
-            uiKeyMapper[KeyCode.K] = EnumCommand.Enter;
-            uiKeyMapper[KeyCode.L] = EnumCommand.Back;
-            uiKeyMapper[KeyCode.I] = EnumCommand.OptionMenu;
-
-            uiKeyMapper[KeyCode.LeftArrow] = EnumCommand.SelectItemLeft;
-            uiKeyMapper[KeyCode.RightArrow] = EnumCommand.SelectItemRight;
-            uiKeyMapper[KeyCode.UpArrow] = EnumCommand.SelectItemUp;
-            uiKeyMapper[KeyCode.DownArrow] = EnumCommand.SelectItemDown;
-            uiKeyMapper[KeyCode.Return] = EnumCommand.Enter;
-            uiKeyMapper[KeyCode.Escape] = EnumCommand.Back;
-            uiKeyMapper[KeyCode.RightShift] = EnumCommand.OptionMenu;
-            uiKeyMapper[KeyCode.LeftShift] = EnumCommand.OptionMenu;
-
-            if (Application.platform == RuntimePlatform.PSP2)
-            {
-                uiKeyMapper[Common.PSVitaKey.Left] = EnumCommand.SelectItemLeft;
-                uiKeyMapper[Common.PSVitaKey.Right] = EnumCommand.SelectItemRight;
-                uiKeyMapper[Common.PSVitaKey.Up] = EnumCommand.SelectItemUp;
-                uiKeyMapper[Common.PSVitaKey.Down] = EnumCommand.SelectItemDown;
-                uiKeyMapper[Common.PSVitaKey.Circle] = EnumCommand.Enter;
-                uiKeyMapper[Common.PSVitaKey.Cross] = EnumCommand.Back;
-                uiKeyMapper[Common.PSVitaKey.Triangle] = EnumCommand.OptionMenu;
-            }
-
-            //PC XBOX
-
-            //uiKeyMapper[Common.PC_XBOXKEY.Left] = EnumCommand.SelectItemLeft;
-            //uiKeyMapper[Common.PSVitaKey.Right] = EnumCommand.SelectItemRight;
-            //uiKeyMapper[Common.PSVitaKey.Up] = EnumCommand.SelectItemUp;
-            //uiKeyMapper[Common.PSVitaKey.Down] = EnumCommand.SelectItemDown;
-            uiKeyMapper[Common.PC_XBOXKEY.MenuBtn] = EnumCommand.Enter;
-            uiKeyMapper[Common.PC_XBOXKEY.ViewBtn] = EnumCommand.Back;
-            uiKeyMapper[Common.PC_XBOXKEY.Y] = EnumCommand.OptionMenu;
-        }
-    }
-}
diff --git a/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NesGamingScheme.cs b/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NesGamingScheme.cs
deleted file mode 100644
index d66360b9..00000000
--- a/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NesGamingScheme.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System.Collections.Generic;
-using UnityEngine;
-
-namespace AxibugEmuOnline.Client
-{
-    public class NesGamingScheme : ControlScheme
-    {
-        public override void SetUIKeys(Dictionary<KeyCode, EnumCommand> uiKeyMapper)
-        {
-            uiKeyMapper[KeyCode.Escape] = EnumCommand.OptionMenu;
-
-            if (Application.platform == RuntimePlatform.PSP2)
-            {
-                uiKeyMapper[Common.PSVitaKey.L] = EnumCommand.OptionMenu;
-                uiKeyMapper[Common.PSVitaKey.R] = EnumCommand.OptionMenu;
-            }
-
-            //PC XBOX
-            uiKeyMapper[Common.PC_XBOXKEY.Y] = EnumCommand.OptionMenu;
-        }
-    }
-
-    public static partial class ControlSchemeSetts
-    {
-        public static NesGamingScheme NES { get; private set; } = new NesGamingScheme();
-    }
-}
diff --git a/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NormalScheme.cs b/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NormalScheme.cs
deleted file mode 100644
index b1d36b89..00000000
--- a/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NormalScheme.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace AxibugEmuOnline.Client
-{
-
-    public class NormalScheme : ControlScheme
-    {
-    }
-
-    public static partial class ControlSchemeSetts
-    {
-        public static NormalScheme Normal { get; private set; } = new NormalScheme();
-    }
-}
diff --git a/AxibugEmuOnline.Client/Assets/Script/ControlSchemes.meta b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger.meta
similarity index 100%
rename from AxibugEmuOnline.Client/Assets/Script/ControlSchemes.meta
rename to AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger.meta
diff --git a/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/CommandChanger.cs b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/CommandChanger.cs
new file mode 100644
index 00000000..a5c98e1d
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/CommandChanger.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace AxibugEmuOnline.Client
+{
+    public abstract class CommandChanger : IKeyMapperChanger
+    {
+        public string Name { get; private set; }
+
+        public abstract object GetConfig();
+    }
+}
diff --git a/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/ControlScheme.cs.meta b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/CommandChanger.cs.meta
similarity index 100%
rename from AxibugEmuOnline.Client/Assets/Script/ControlSchemes/ControlScheme.cs.meta
rename to AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/CommandChanger.cs.meta
diff --git a/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/GamingChanger.cs b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/GamingChanger.cs
new file mode 100644
index 00000000..cb62ac53
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/GamingChanger.cs
@@ -0,0 +1,10 @@
+namespace AxibugEmuOnline.Client
+{
+    public class GamingChanger : CommandChanger
+    {
+        public override object GetConfig()
+        {
+            return "UI_InGame";
+        }
+    }
+}
diff --git a/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NormalScheme.cs.meta b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/GamingChanger.cs.meta
similarity index 83%
rename from AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NormalScheme.cs.meta
rename to AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/GamingChanger.cs.meta
index 41f00f7c..9eb3de0c 100644
--- a/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NormalScheme.cs.meta
+++ b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/GamingChanger.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: d43d5934b9afba14782405dc1b6eb455
+guid: e5b6687e9412f174d82b2c15f1efc4a4
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy.meta b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy.meta
new file mode 100644
index 00000000..c26d03bb
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: d5a7a9a2191170e49b387c0487288ae9
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/GamingChanger_Legacy.cs b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/GamingChanger_Legacy.cs
new file mode 100644
index 00000000..250cee93
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/GamingChanger_Legacy.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace AxibugEmuOnline.Client
+{
+    public class GamingChanger_Legacy : CommandChanger
+    {
+        Dictionary<KeyCode, EnumCommand> m_uiKeyMapper = new Dictionary<KeyCode, EnumCommand>();
+        public GamingChanger_Legacy()
+        {
+            m_uiKeyMapper[KeyCode.Escape] = EnumCommand.OptionMenu;
+
+            if (Application.platform == RuntimePlatform.PSP2)
+            {
+                m_uiKeyMapper[Common.PSVitaKey.L] = EnumCommand.OptionMenu;
+                m_uiKeyMapper[Common.PSVitaKey.R] = EnumCommand.OptionMenu;
+            }
+
+            //PC XBOX
+            m_uiKeyMapper[Common.PC_XBOXKEY.Y] = EnumCommand.OptionMenu;
+        }
+
+        public override object GetConfig() => m_uiKeyMapper;
+    }
+}
diff --git a/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NesGamingScheme.cs.meta b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/GamingChanger_Legacy.cs.meta
similarity index 83%
rename from AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NesGamingScheme.cs.meta
rename to AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/GamingChanger_Legacy.cs.meta
index b87af5ce..014e1117 100644
--- a/AxibugEmuOnline.Client/Assets/Script/ControlSchemes/NesGamingScheme.cs.meta
+++ b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/GamingChanger_Legacy.cs.meta
@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: a90914c97f6349a4e96302cc0ceeeed0
+guid: c8339ffab20bfea4cbc7d3aa440c3fdb
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2
diff --git a/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/NormalChanger_Legacy.cs b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/NormalChanger_Legacy.cs
new file mode 100644
index 00000000..2d328d99
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/NormalChanger_Legacy.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using UnityEngine;
+
+namespace AxibugEmuOnline.Client
+{
+
+    public class NormalChanger_Legacy : CommandChanger
+    {
+        Dictionary<KeyCode, EnumCommand> m_uiKeyMapper = new Dictionary<KeyCode, EnumCommand>();
+        public NormalChanger_Legacy()
+        {
+            m_uiKeyMapper[KeyCode.A] = EnumCommand.SelectItemLeft;
+            m_uiKeyMapper[KeyCode.D] = EnumCommand.SelectItemRight;
+            m_uiKeyMapper[KeyCode.W] = EnumCommand.SelectItemUp;
+            m_uiKeyMapper[KeyCode.S] = EnumCommand.SelectItemDown;
+            m_uiKeyMapper[KeyCode.K] = EnumCommand.Enter;
+            m_uiKeyMapper[KeyCode.L] = EnumCommand.Back;
+            m_uiKeyMapper[KeyCode.I] = EnumCommand.OptionMenu;
+
+            m_uiKeyMapper[KeyCode.LeftArrow] = EnumCommand.SelectItemLeft;
+            m_uiKeyMapper[KeyCode.RightArrow] = EnumCommand.SelectItemRight;
+            m_uiKeyMapper[KeyCode.UpArrow] = EnumCommand.SelectItemUp;
+            m_uiKeyMapper[KeyCode.DownArrow] = EnumCommand.SelectItemDown;
+            m_uiKeyMapper[KeyCode.Return] = EnumCommand.Enter;
+            m_uiKeyMapper[KeyCode.Escape] = EnumCommand.Back;
+            m_uiKeyMapper[KeyCode.RightShift] = EnumCommand.OptionMenu;
+            m_uiKeyMapper[KeyCode.LeftShift] = EnumCommand.OptionMenu;
+
+            if (Application.platform == RuntimePlatform.PSP2)
+            {
+                m_uiKeyMapper[Common.PSVitaKey.Left] = EnumCommand.SelectItemLeft;
+                m_uiKeyMapper[Common.PSVitaKey.Right] = EnumCommand.SelectItemRight;
+                m_uiKeyMapper[Common.PSVitaKey.Up] = EnumCommand.SelectItemUp;
+                m_uiKeyMapper[Common.PSVitaKey.Down] = EnumCommand.SelectItemDown;
+                m_uiKeyMapper[Common.PSVitaKey.Circle] = EnumCommand.Enter;
+                m_uiKeyMapper[Common.PSVitaKey.Cross] = EnumCommand.Back;
+                m_uiKeyMapper[Common.PSVitaKey.Triangle] = EnumCommand.OptionMenu;
+            }
+
+            //PC XBOX
+
+            //m_uiKeyMapper[Common.PC_XBOXKEY.Left] = EnumCommand.SelectItemLeft;
+            //m_uiKeyMapper[Common.PSVitaKey.Right] = EnumCommand.SelectItemRight;
+            //m_uiKeyMapper[Common.PSVitaKey.Up] = EnumCommand.SelectItemUp;
+            //m_uiKeyMapper[Common.PSVitaKey.Down] = EnumCommand.SelectItemDown;
+            m_uiKeyMapper[Common.PC_XBOXKEY.MenuBtn] = EnumCommand.Enter;
+            m_uiKeyMapper[Common.PC_XBOXKEY.ViewBtn] = EnumCommand.Back;
+            m_uiKeyMapper[Common.PC_XBOXKEY.Y] = EnumCommand.OptionMenu;
+        }
+
+        public override object GetConfig() => m_uiKeyMapper;
+    }
+
+}
diff --git a/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/NormalChanger_Legacy.cs.meta b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/NormalChanger_Legacy.cs.meta
new file mode 100644
index 00000000..2740c3f1
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/Legacy/NormalChanger_Legacy.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: b8790f215d873d044aa8d00bacdee237
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/NormalChanger.cs b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/NormalChanger.cs
new file mode 100644
index 00000000..7ea16b2a
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/NormalChanger.cs
@@ -0,0 +1,10 @@
+namespace AxibugEmuOnline.Client
+{
+    public class NormalChanger : CommandChanger
+    {
+        public override object GetConfig()
+        {
+            return "UI_Normal";
+        }
+    }
+}
diff --git a/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/NormalChanger.cs.meta b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/NormalChanger.cs.meta
new file mode 100644
index 00000000..51b84083
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/IkeyMapperChanger/NormalChanger.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 8aa965a6a15aa1a4195977111b1ec13b
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/AxibugEmuOnline.Client/Assets/Script/Manager/AppEmu.cs b/AxibugEmuOnline.Client/Assets/Script/Manager/AppEmu.cs
index b16b04f2..5e9c626a 100644
--- a/AxibugEmuOnline.Client/Assets/Script/Manager/AppEmu.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/Manager/AppEmu.cs
@@ -71,7 +71,7 @@ namespace AxibugEmuOnline.Client.Manager
             InGameUI.Instance.Hide();
             LaunchUI.Instance.ShowMainMenu();
 
-            ControlScheme.Current = ControlSchemeSetts.Normal;
+            CommandDispatcher.Instance.Current = CommandDispatcher.Instance.Normal;
         }
 
         public void ResetGame()
diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.cs b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.cs
index d84123eb..20c79108 100644
--- a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.cs
@@ -135,7 +135,7 @@ namespace AxibugEmuOnline.Client
 
         public void SetupScheme()
         {
-            ControlScheme.Current = ControlSchemeSetts.NES;
+            CommandDispatcher.Instance.Current = CommandDispatcher.Instance.Gaming;
         }
 
         public void LoadState(object state)
diff --git a/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandDispatcher.cs b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandDispatcher.cs
index 1a874a79..a9b0c342 100644
--- a/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandDispatcher.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandDispatcher.cs
@@ -12,11 +12,47 @@ namespace AxibugEmuOnline.Client
         /// <summary> ��ռע�����,ָ��ᱻ�б������һ�������ռ </summary>
         List<CommandExecuter> m_registerHigh = new List<CommandExecuter>();
 
-        Dictionary<KeyCode, EnumCommand> m_keyMapper = new Dictionary<KeyCode, EnumCommand>();
+        ICommandListener m_listener;
+        /// <summary> ��׼UI���� </summary>
+        public IKeyMapperChanger Normal { get; private set; }
+        /// <summary> ��Ϸ��UI���� </summary>
+        public IKeyMapperChanger Gaming { get; private set; }
+
+        public bool LegacyInput;
+
+        private IKeyMapperChanger m_current;
+        public IKeyMapperChanger Current
+        {
+            get => m_current;
+            set
+            {
+                m_current = value;
+
+                SetKeyMapper(m_current);
+            }
+        }
 
         private void Awake()
         {
             Instance = this;
+
+            //��ʼ��command������
+            if (LegacyInput)
+                m_listener = new CommandListener_Legacy();
+            else
+                m_listener = new CommandListener();
+
+            //��ʼ����λ�޸���
+            if (LegacyInput)
+            {
+                Normal = new NormalChanger_Legacy();
+                Gaming = new GamingChanger_Legacy();
+            }
+            else
+            {
+                Normal = new NormalChanger();
+                Gaming = new GamingChanger();
+            }
         }
 
         private void OnDestroy()
@@ -51,40 +87,21 @@ namespace AxibugEmuOnline.Client
         readonly List<CommandExecuter> oneFrameRegister = new List<CommandExecuter>();
         private void Update()
         {
-            foreach (var item in m_keyMapper)
-            {
-                peekRegister(oneFrameRegister);
+            peekRegister(oneFrameRegister);
+            m_listener.Update(oneFrameRegister);
 
-                if (Input.GetKeyDown(item.Key))
-                {
-                    foreach (var controller in oneFrameRegister)
-                    {
-                        if (!controller.Enable) continue;
-                        controller.ExecuteCommand(item.Value, false);
-                    }
-                }
-                if (Input.GetKeyUp(item.Key))
-                {
-                    foreach (var controller in oneFrameRegister)
-                    {
-                        if (!controller.Enable) continue;
-                        controller.ExecuteCommand(item.Value, true);
-                    }
-                }
-            }
-
-            //��λӳ�����Ҫ�ڰ�����Ӧ�Ķ�ջ��������,��ֹ�������޸�����
+            //��λӳ���ڰ�����Ӧ�Ķ�ջ��������,��ֹ�������޸�����
             if (m_waitMapperSetting != null)
             {
-                m_keyMapper = m_waitMapperSetting;
+                m_listener.ApplyKeyMapper(m_waitMapperSetting);
                 m_waitMapperSetting = null;
             }
         }
 
-        private Dictionary<KeyCode, EnumCommand> m_waitMapperSetting = null;
-        public void SetKeyMapper(Dictionary<KeyCode, EnumCommand> mapper)
+        IKeyMapperChanger m_waitMapperSetting = null;
+        void SetKeyMapper(IKeyMapperChanger keyMapChanger)
         {
-            m_waitMapperSetting = mapper;
+            m_waitMapperSetting = keyMapChanger;
         }
 
         private List<CommandExecuter> peekRegister(List<CommandExecuter> results)
@@ -114,7 +131,6 @@ namespace AxibugEmuOnline.Client
             return results;
         }
 
-
 #if UNITY_EDITOR
         public void GetRegisters(out IReadOnlyList<CommandExecuter> normal, out IReadOnlyList<CommandExecuter> alone)
         {
diff --git a/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener.cs b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener.cs
new file mode 100644
index 00000000..e7ee8dd6
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.InputSystem;
+
+namespace AxibugEmuOnline.Client
+{
+    public class CommandListener : ICommandListener
+    {
+        private PlayerInput m_uiInput;
+        private IEnumerable<CommandExecuter> m_executers;
+
+        public CommandListener()
+        {
+            m_uiInput = GameObject.FindGameObjectWithTag("UIInput").GetComponent<PlayerInput>();
+            m_uiInput.onActionTriggered += M_uiInput_onActionTriggered;
+        }
+        public void Update(IEnumerable<CommandExecuter> executer)
+        {
+            m_executers = executer;
+        }
+
+        private void M_uiInput_onActionTriggered(InputAction.CallbackContext obj)
+        {
+            CommandState? cs = null;
+            switch (obj.action.phase)
+            {
+                case InputActionPhase.Started:
+                    cs = new CommandState { Cancel = false, Cmd = ToCommandEnum(obj.action.name) };
+                    break;
+                case InputActionPhase.Canceled:
+                    cs = new CommandState { Cancel = true, Cmd = ToCommandEnum(obj.action.name) };
+                    break;
+            }
+            if (!cs.HasValue) return;
+
+            foreach (var exec in m_executers)
+            {
+                if (!exec.Enable) continue;
+                exec.ExecuteCommand(cs.Value.Cmd, cs.Value.Cancel);
+            }
+        }
+
+        public void ApplyKeyMapper(IKeyMapperChanger changer)
+        {
+            var actionMapName = (string)changer.GetConfig();
+            m_uiInput.SwitchCurrentActionMap(actionMapName);
+        }
+
+        EnumCommand ToCommandEnum(string actionName)
+        {
+            return actionName switch
+            {
+                "SelectItemLeft" => EnumCommand.SelectItemLeft,
+                "SelectItemRight" => EnumCommand.SelectItemRight,
+                "SelectItemUp" => EnumCommand.SelectItemUp,
+                "SelectItemDown" => EnumCommand.SelectItemDown,
+                "Enter" => EnumCommand.Enter,
+                "Back" => EnumCommand.Back,
+                "OptionMenu" => EnumCommand.OptionMenu,
+                _ => throw new Exception("Not Support Action")
+            };
+        }
+    }
+}
diff --git a/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener.cs.meta b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener.cs.meta
new file mode 100644
index 00000000..98279440
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: a493da4af70f32a43b3c558d94cf23a4
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener_Legacy.cs b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener_Legacy.cs
new file mode 100644
index 00000000..8598135b
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener_Legacy.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace AxibugEmuOnline.Client
+{
+    public class CommandListener_Legacy : ICommandListener
+    {
+        Dictionary<KeyCode, EnumCommand> m_keyMapper = new Dictionary<KeyCode, EnumCommand>();
+        List<CommandState> m_commands = new List<CommandState>();
+        IEnumerable<CommandState> GetCommand()
+        {
+            m_commands.Clear();
+            foreach (var item in m_keyMapper)
+            {
+                if (Input.GetKeyDown(item.Key)) m_commands.Add(new CommandState { Cmd = item.Value, Cancel = false });
+                if (Input.GetKeyUp(item.Key)) m_commands.Add(new CommandState { Cmd = item.Value, Cancel = true });
+            }
+
+            return m_commands;
+        }
+        public void ApplyKeyMapper(IKeyMapperChanger changer)
+        {
+            var cfg = (Dictionary<KeyCode, EnumCommand>)changer.GetConfig();
+            m_keyMapper = cfg;
+        }
+
+        public void Update(IEnumerable<CommandExecuter> executers)
+        {
+            foreach (var cmd in GetCommand())
+            {
+                foreach (var executer in executers)
+                {
+                    executer.ExecuteCommand(cmd.Cmd, cmd.Cancel);
+                }
+            }
+        }
+    }
+}
diff --git a/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener_Legacy.cs.meta b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener_Legacy.cs.meta
new file mode 100644
index 00000000..772b3c2e
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/CommandListener_Legacy.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 0c54554335d283d4ca61e01335c58665
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/ICommandListener.cs b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/ICommandListener.cs
new file mode 100644
index 00000000..11861229
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/ICommandListener.cs
@@ -0,0 +1,24 @@
+using System.Collections.Generic;
+
+namespace AxibugEmuOnline.Client
+{
+    public interface IKeyMapperChanger
+    {
+        object GetConfig();
+    }
+    public interface ICommandListener
+    {
+        /// <summary>
+        /// 应用键位设置
+        /// </summary>
+        /// <param name="changer"></param>
+        void ApplyKeyMapper(IKeyMapperChanger changer);
+        void Update(IEnumerable<CommandExecuter> commands);
+    }
+
+    public struct CommandState
+    {
+        public EnumCommand Cmd;
+        public bool Cancel;
+    }
+}
diff --git a/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/ICommandListener.cs.meta b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/ICommandListener.cs.meta
new file mode 100644
index 00000000..c0418c61
--- /dev/null
+++ b/AxibugEmuOnline.Client/Assets/Script/UI/CommandDispatcher/ICommandListener.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 16e65b8db21c226419b57118ec1f56ff
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/AxibugEmuOnline.Client/Assets/Script/UI/InGameUI/InGameUI.cs b/AxibugEmuOnline.Client/Assets/Script/UI/InGameUI/InGameUI.cs
index 48ee3933..d64cdaa5 100644
--- a/AxibugEmuOnline.Client/Assets/Script/UI/InGameUI/InGameUI.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/UI/InGameUI/InGameUI.cs
@@ -124,7 +124,7 @@ namespace AxibugEmuOnline.Client
             App.roomMgr.SendLeavnRoom();
             App.emu.StopGame();
 
-            ControlScheme.Current = ControlSchemeSetts.Normal;
+            CommandDispatcher.Instance.Current = CommandDispatcher.Instance.Normal;
         }
     }
 }
diff --git a/AxibugEmuOnline.Client/Assets/Script/UI/LaunchUI.cs b/AxibugEmuOnline.Client/Assets/Script/UI/LaunchUI.cs
index 2b301746..9ad8905f 100644
--- a/AxibugEmuOnline.Client/Assets/Script/UI/LaunchUI.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/UI/LaunchUI.cs
@@ -36,7 +36,7 @@ namespace AxibugEmuOnline.Client
 
         private void Start()
         {
-            ControlScheme.Current = ControlSchemeSetts.Normal;
+            CommandDispatcher.Instance.Current = CommandDispatcher.Instance.Normal;
         }
 
         public void HideMainMenu()
diff --git a/AxibugEmuOnline.Client/Assets/Script/UI/OptionUI/OptionUI.cs b/AxibugEmuOnline.Client/Assets/Script/UI/OptionUI/OptionUI.cs
index e6f4d05c..3aa908d5 100644
--- a/AxibugEmuOnline.Client/Assets/Script/UI/OptionUI/OptionUI.cs
+++ b/AxibugEmuOnline.Client/Assets/Script/UI/OptionUI/OptionUI.cs
@@ -125,7 +125,7 @@ namespace AxibugEmuOnline.Client
             }
         }
 
-        ControlScheme m_lastCS;
+        IKeyMapperChanger m_lastCS;
         public void Pop<T>(List<T> menus, int defaultIndex = 0) where T : OptionMenu
         {
             ReleaseRuntimeMenus();
@@ -160,8 +160,8 @@ namespace AxibugEmuOnline.Client
                     0.3f
                     ).SetEase(Ease.OutCubic);
 
-                m_lastCS = ControlScheme.Current;
-                ControlScheme.Current = ControlSchemeSetts.Normal;
+                m_lastCS = CommandDispatcher.Instance.Current;
+                CommandDispatcher.Instance.Current = CommandDispatcher.Instance.Normal;
             }
 
         }
@@ -192,7 +192,7 @@ namespace AxibugEmuOnline.Client
 
                 m_bPoped = false;
 
-                ControlScheme.Current = m_lastCS;
+                CommandDispatcher.Instance.Current = m_lastCS;
 
                 OnHide?.Invoke();
             }
diff --git a/AxibugEmuOnline.Client/ProjectSettings/ProjectSettings.asset b/AxibugEmuOnline.Client/ProjectSettings/ProjectSettings.asset
index 641bd9f5..ed6fd664 100644
--- a/AxibugEmuOnline.Client/ProjectSettings/ProjectSettings.asset
+++ b/AxibugEmuOnline.Client/ProjectSettings/ProjectSettings.asset
@@ -744,7 +744,7 @@ PlayerSettings:
     m_VersionCode: 1
     m_VersionName: 
   apiCompatibilityLevel: 3
-  activeInputHandler: 0
+  activeInputHandler: 2
   cloudProjectId: 
   framebufferDepthMemorylessMode: 0
   qualitySettingsNames: []
diff --git a/AxibugEmuOnline.Client/ProjectSettings/TagManager.asset b/AxibugEmuOnline.Client/ProjectSettings/TagManager.asset
index 1c92a784..e8cbe7e6 100644
--- a/AxibugEmuOnline.Client/ProjectSettings/TagManager.asset
+++ b/AxibugEmuOnline.Client/ProjectSettings/TagManager.asset
@@ -3,7 +3,8 @@
 --- !u!78 &1
 TagManager:
   serializedVersion: 2
-  tags: []
+  tags:
+  - UIInput
   layers:
   - Default
   - TransparentFX