本文將提供更簡潔的步驟和常見問題解決。
一、極簡入門步驟:
-
安裝:Package Manager中安裝Input System(確保Unity版本在2019.4+)
-
創建Input Actions:
-
在Project窗口右鍵 -> Create -> Input Actions
-
雙擊打開編輯器,添加Action Map(例如"Player")
-
在Action Map中添加Action(例如"Move"、“Jump”)
-
為每個Action添加綁定,例如:
-
“Move”:綁定到/leftStick 和 /wasd
-
“Jump”:綁定到/space 和 /buttonSouth
- 生成C#類:
-
在Input Actions資源的Inspector中,勾選"Generate C# Class"
-
點擊"Apply",生成一個與資源同名的C#腳本
- 在代碼中使用:
using UnityEngine;using UnityEngine.InputSystem;public class Example : MonoBehaviour{private PlayerInputActions inputActions;void Awake(){inputActions = new PlayerInputActions();inputActions.Player.Enable();}void Update(){Vector2 move = inputActions.Player.Move.ReadValue<Vector2>();// 使用move移動角色}void OnJumpPerformed(InputAction.CallbackContext context){// 跳躍}void OnEnable(){inputActions.Player.Jump.performed += OnJumpPerformed;}void OnDisable(){inputActions.Player.Jump.performed -= OnJumpPerformed;}}
- 使用PlayerInput組件(可選):
-
將Input Actions資源拖到PlayerInput組件的"Actions"屬性
-
選擇行為模式(如"Invoke Unity Events")并配置事件
常見問題及解決:
- 輸入不生效:
-
檢查是否啟用了Action Map:
inputActions.Player.Enable();
-
檢查Project Settings中Active Input Handling是否選擇了"Input System Package"
-
重啟Unity(有時安裝后需要重啟)
- 如何在多個腳本中使用同一個輸入?
- 推薦創建一個單例管理輸入,或者將Input Actions實例作為參數傳遞給其他腳本
- 如何實現雙人游戲?
-
使用
PlayerInputManager
組件 -
在場景中添加一個空物體,掛載
PlayerInputManager
-
設置玩家預制體(Prefab),在預制體上添加
PlayerInput
組件并配置Input Actions -
通過
PlayerInputManager
動態創建玩家實例
- 如何實現按鍵重綁定?
// 找到要重綁定的Actionvar action = inputActions.FindAction("Player/Jump");// 開始重綁定var rebindOperation = action.PerformInteractiveRebinding().WithControlsExcluding("<Mouse>/press").OnMatchWaitForAnother(0.1f).Start();
- 如何切換操作方案(如行走和駕駛)?
-
使用不同的Action Map
-
切換時禁用當前Action Map,啟用另一個:
inputActions.Player.Disable();inputActions.Vehicle.Enable();
- 如何獲取當前設備類型(判斷是手柄還是鍵盤)?
// 通過PlayerInput組件PlayerInput playerInput = GetComponent<PlayerInput>();string deviceType = playerInput.currentControlScheme;// 或者監聽設備變化playerInput.onControlsChanged += (PlayerInput input) =>{Debug.Log(input.currentControlScheme);};
調試技巧:
-
打開菜單:Window -> Analysis -> Input Debugger,查看實時輸入
-
在代碼中監聽輸入事件,打印日志
希望這個快速指南能解決你的問題!如果遇到特定問題,請提供更多細節。
二、Unity Input System 全面使用指南
Unity 的新輸入系統提供了更強大、靈活的輸入處理方式,下面我將通過一個完整的示例項目展示如何使用它。
安裝與設置
-
安裝 Input System:
- 打開 Package Manager (Window > Package Manager)
- 選擇 “Unity Registry”
- 找到 “Input System” 并安裝
-
啟用新輸入系統:
- 前往 Edit > Project Settings > Player
- 在 “Other Settings” 部分:
- Active Input Handling: 選擇 “Input System Package (New)”
創建輸入配置
步驟 1:創建 Input Actions Asset
- 在 Project 窗口右鍵 > Create > Input Actions
- 命名為 “PlayerControls”
步驟 2:配置輸入動作
雙擊打開 PlayerControls 進行編輯:
Action Map | Action | Binding | Control Path |
---|---|---|---|
Player | Move | 2D Vector | WASD / Left Stick |
Player | Jump | Button | Space / Gamepad South |
Player | Look | 2D Vector | Mouse Delta / Right Stick |
Player | Fire | Button | Mouse Left / Gamepad East |
UI | Navigate | 2D Vector | Arrow Keys / Left Stick |
UI | Submit | Button | Enter / Gamepad South |
代碼實現
基礎移動控制器
using UnityEngine;
using UnityEngine.InputSystem;[RequireComponent(typeof(CharacterController))]
public class PlayerController : MonoBehaviour
{[Header("Movement Settings")][SerializeField] private float moveSpeed = 5f;[SerializeField] private float jumpHeight = 2f;[SerializeField] private float gravity = -9.81f;[SerializeField] private float rotationSpeed = 10f;[Header("Camera")][SerializeField] private Transform cameraTransform;private CharacterController controller;private PlayerInput playerInput;private InputAction moveAction;private InputAction jumpAction;private InputAction lookAction;private Vector3 velocity;private bool isGrounded;private float rotationX = 0f;private void Awake(){controller = GetComponent<CharacterController>();playerInput = GetComponent<PlayerInput>();// 獲取輸入動作moveAction = playerInput.actions["Move"];jumpAction = playerInput.actions["Jump"];lookAction = playerInput.actions["Look"];// 鎖定鼠標Cursor.lockState = CursorLockMode.Locked;}private void Update(){// 地面檢測isGrounded = controller.isGrounded;if (isGrounded && velocity.y < 0){velocity.y = -2f;}// 移動Vector2 moveInput = moveAction.ReadValue<Vector2>();Vector3 moveDirection = new Vector3(moveInput.x, 0, moveInput.y);moveDirection = Quaternion.Euler(0, cameraTransform.eulerAngles.y, 0) * moveDirection;controller.Move(moveDirection * moveSpeed * Time.deltaTime);// 跳躍if (jumpAction.triggered && isGrounded){velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);}// 重力velocity.y += gravity * Time.deltaTime;controller.Move(velocity * Time.deltaTime);// 視角旋轉Vector2 lookInput = lookAction.ReadValue<Vector2>();float mouseX = lookInput.x * rotationSpeed * Time.deltaTime;float mouseY = lookInput.y * rotationSpeed * Time.deltaTime;rotationX -= mouseY;rotationX = Mathf.Clamp(rotationX, -90f, 90f);cameraTransform.localRotation = Quaternion.Euler(rotationX, 0, 0);transform.Rotate(Vector3.up * mouseX);}
}
UI 輸入處理
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;public class UIController : MonoBehaviour
{[SerializeField] private Button startButton;[SerializeField] private Slider volumeSlider;private PlayerInput playerInput;private InputAction navigateAction;private InputAction submitAction;private void Awake(){playerInput = GetComponent<PlayerInput>();// 切換到UI輸入映射playerInput.SwitchCurrentActionMap("UI");// 獲取輸入動作navigateAction = playerInput.actions["Navigate"];submitAction = playerInput.actions["Submit"];// 注冊輸入事件navigateAction.performed += OnNavigate;submitAction.performed += OnSubmit;}private void OnNavigate(InputAction.CallbackContext context){Vector2 direction = context.ReadValue<Vector2>();// 簡單的UI導航邏輯if (Mathf.Abs(direction.y) > 0.5f){if (direction.y > 0) volumeSlider.Select();else startButton.Select();}}private void OnSubmit(InputAction.CallbackContext context){// 模擬按鈕點擊if (startButton.gameObject == UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject){startButton.onClick.Invoke();}}private void OnDestroy(){navigateAction.performed -= OnNavigate;submitAction.performed -= OnSubmit;}
}
高級功能實現
輸入重綁定系統
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;public class RebindManager : MonoBehaviour
{[SerializeField] private InputActionReference targetAction;[SerializeField] private Text bindingText;[SerializeField] private GameObject waitingPanel;private InputActionRebindingExtensions.RebindingOperation rebindingOperation;public void StartRebinding(){waitingPanel.SetActive(true);bindingText.text = "Press any key...";// 取消當前綁定targetAction.action.Disable();// 開始重綁定rebindingOperation = targetAction.action.PerformInteractiveRebinding().WithControlsExcluding("<Mouse>/position").WithControlsExcluding("<Mouse>/delta").WithControlsExcluding("<Gamepad>/Start").OnMatchWaitForAnother(0.1f).OnComplete(operation => RebindComplete()).Start();}private void RebindComplete(){// 保存新綁定string rebinds = rebindingOperation.action.SaveBindingOverridesAsJson();PlayerPrefs.SetString("rebinds", rebinds);// 更新UI顯示bindingText.text = InputControlPath.ToHumanReadableString(targetAction.action.bindings[0].effectivePath,InputControlPath.HumanReadableStringOptions.OmitDevice);// 清理操作rebindingOperation.Dispose();waitingPanel.SetActive(false);targetAction.action.Enable();}private void OnEnable(){// 加載保存的重綁定if (PlayerPrefs.HasKey("rebinds")){string rebinds = PlayerPrefs.GetString("rebinds");targetAction.action.LoadBindingOverridesFromJson(rebinds);}// 初始化顯示bindingText.text = InputControlPath.ToHumanReadableString(targetAction.action.bindings[0].effectivePath,InputControlPath.HumanReadableStringOptions.OmitDevice);}
}
設備檢測與切換
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;public class DeviceDisplay : MonoBehaviour
{[SerializeField] private Text deviceText;[SerializeField] private Image keyboardIcon;[SerializeField] private Image gamepadIcon;private PlayerInput playerInput;private void Awake(){playerInput = FindObjectOfType<PlayerInput>();playerInput.onControlsChanged += OnControlsChanged;UpdateDeviceDisplay();}private void OnControlsChanged(PlayerInput input){UpdateDeviceDisplay();}private void UpdateDeviceDisplay(){string deviceName = "Unknown";if (playerInput.currentControlScheme == "KeyboardMouse"){deviceName = "Keyboard & Mouse";keyboardIcon.gameObject.SetActive(true);gamepadIcon.gameObject.SetActive(false);}else if (playerInput.currentControlScheme == "Gamepad"){deviceName = "Gamepad";keyboardIcon.gameObject.SetActive(false);gamepadIcon.gameObject.SetActive(true);}deviceText.text = $"Current Device: {deviceName}";}private void OnDestroy(){if (playerInput != null){playerInput.onControlsChanged -= OnControlsChanged;}}
}
最佳實踐與技巧
-
輸入處理模式選擇:
- 對于簡單項目:使用
Invoke Unity Events
模式 - 對于復雜項目:使用
Invoke C# Events
或直接訪問輸入動作
- 對于簡單項目:使用
-
輸入動作組織:
- 按功能分組(Player、UI、Vehicle等)
- 為常用操作設置復合綁定(如WASD綁定為2D向量)
-
多玩家輸入:
// 在玩家加入時 public void OnPlayerJoined(PlayerInput playerInput) {// 為每個玩家設置不同的輸入設備if (playerInput.playerIndex == 0){playerInput.SwitchCurrentControlScheme("KeyboardMouse", Keyboard.current);}else{playerInput.SwitchCurrentControlScheme("Gamepad", Gamepad.current);} }
-
輸入處理優化:
- 使用
InputAction.CallbackContext
代替每幀檢查 - 在不需要時禁用輸入動作以節省資源
- 使用
-
移動設備支持:
- 使用
Touchscreen
輸入 - 添加虛擬搖桿和按鈕
// 在Input Actions中創建觸摸輸入 public void SetupTouchControls() {// 添加觸摸輸入動作var touchAction = new InputAction("TouchPosition", binding: "<Touchscreen>/position");touchAction.Enable();// 添加點擊動作var tapAction = new InputAction("PrimaryTouch", binding: "<Touchscreen>/primaryTouch/tap");tapAction.Enable(); }
- 使用
調試技巧
-
使用 Input Debugger:
- Window > Analysis > Input Debugger
- 實時查看所有輸入設備狀態
-
在編輯器中模擬設備:
- 打開 Input Debugger
- 點擊 “Add Device” 添加虛擬設備
- 使用虛擬設備測試輸入
-
記錄輸入事件:
private void OnEnable() {InputSystem.onEvent += OnInputEvent; }private void OnDisable() {InputSystem.onEvent -= OnInputEvent; }private void OnInputEvent(InputEventPtr eventPtr, InputDevice device) {// 記錄輸入事件Debug.Log($"Input event from {device.name}"); }
這個全面的指南覆蓋了Unity Input System的核心功能和使用方法。根據你的項目需求選擇合適的實現方式,并記得在復雜項目中合理組織輸入動作和綁定。