[Unity] 新版 Input System 基礎用法教學 – WASD 移動物件(可斜走)

Unity 早已發佈新版的輸入系統「Input System」,是個不同於以往在 Update 塞 Input.GetKey 的輸入方式,它使用更好的委派/事件來處理這些行為。

但在 Input System 中要用委派來處理物件移動的話,會出現無法輸出同時按下複數按鍵後的狀況「角色不能斜走」。這就是我們在這篇文章中要來解決的問題,這邊會從 Input System 的安裝開始說明,操作正文請直接跳至 建立 WASD 輸入行為

Input System 僅支援 Unity 2019.1 或更新版本編輯器

設定 Project Settings

首先,從 Editor 開啟 Project Settings,並切換到 Player 頁面。

往下滑,將 Active Input Handling 改成 Input System Package 或 Both,如果新舊版都會用到的話就選擇 Both。

修改後要讓編輯器重開。

安裝 Input System

從 Window 開啟 Package Manager。

左上角切換到 Unity Registry 後,找到 Input System 後安裝。

建立 WASD 輸入行為

在 Project 的 Assets 目錄下滑鼠右鍵 > Create > Input Actions,取名為「InputMaster」。

點擊 InputMaster,將 Generate C# Class 打勾後按下 Apply,再點擊 Edit asset 開啟編輯介面。

由左到右分別是 Action Maps、Actions 與 Properties 區塊,這些我們都會用到。

首先,點擊左上角的 No Control Schemes > Add Control Scheme。

新增一個 Control Scheme 並取名為 Keyboard,硬體列表也要新增 Keyboard 進去,這是規定接下來要新增的輸入行為要適用於那些硬體。

新增一個 Action Maps 取名為 Player,再將它自動建立的 Actions 名稱改為 Movement,然後把它給的 <No Blinding> 給刪除。(滑鼠右鍵選單 > Delete)

點擊 Movement,看到 Properties 區塊,將 Action Type 改為 Value、Control Type 改為 Vector 2。這動作的用意是要讓它輸出的數值是二維向量,待會才能將它取出來讓物件動。

前面我有講過,它是以委派/事件的方式來處理輸入,所以我們必須監聽按鍵按下與放開兩種狀態,才能讓物件移動與停止。

在 Properties 區塊的 Interactions 新增一個 Press,並將 Trigger Behavior 改成 Press And Release。

接下來定義輸入按鍵,按下 Movement 的加號,選擇 Add 2D Vector Composite。

將上下左右設定綁好 WASD 按鍵。

最後按下 Save Asset 儲存。

設計角色移動腳本

我們就以一個 Character Controller 組件的 Cube 作為例子,設計一個依靠前面建立的 InputMaster 來操控物件前後左右自由移動。

將 InputMaster New 出來後,要記得下 Enable() 來讓他可以動作。之後就能在 Update 中用 ReadValue 來讀取二維向量值,而且在同時按下不同按鍵時會自動計算向量積以維持移動的單位長度為 1。

using UnityEngine;
[RequireComponent(typeof(CharacterController))]
public class PlayerMovementController : MonoBehaviour
{
    public InputMaster inputMaster;
    public CharacterController characterController;
    public float moveSpeed = 10;
#if UNITY_EDITOR
    private void OnValidate()
    {
        characterController = GetComponent<CharacterController>();
    }
#endif
    private void Awake()
    {
        inputMaster = new InputMaster();
        inputMaster.Enable();
    }
    private void Update()
    {
        Vector2 vector2d = inputMaster.Player.Movement.ReadValue<Vector2>();
        if (vector2d != Vector2.zero)
        {
            Vector3 vector3d = new Vector3(vector2d.x, 0, vector2d.y);
            Vector3 direction = transform.TransformDirection(vector3d);
            characterController.Move(direction * moveSpeed * Time.deltaTime);
        }
    }
}

而新版 Input System 除了直接 ReadValue 之外還有委派的用法,可以在按下按鍵後才觸發 ReadValue,但是這有個缺點,它的運作模式會造成角色不能斜走,複數方向按鍵同時觸發時只會執行第一個按鍵的結果。

在 Awake 中,在我們的 Movement 下註冊 performed 後即可從他帶的參數中取得數值。

using UnityEngine;
[RequireComponent(typeof(CharacterController))]
public class PlayerMovementController_Delegate : MonoBehaviour
{
    public InputMaster inputMaster;
    public CharacterController characterController;
    public float moveSpeed = 10;
    private Vector2 vector2d;
#if UNITY_EDITOR
    private void OnValidate()
    {
        characterController = GetComponent<CharacterController>();
    }
#endif
    private void Awake()
    {
        inputMaster = new InputMaster();
        inputMaster.Enable();
        inputMaster.Player.Movement.performed += ctx =>
        {
            vector2d = ctx.ReadValue<Vector2>();
        };
    }
    private void Update()
    {
        if (vector2d != Vector2.zero)
        {
            Vector3 vector3d = new Vector3(vector2d.x, 0, vector2d.y);
            Vector3 direction = transform.TransformDirection(vector3d);
            characterController.Move(direction * moveSpeed * Time.deltaTime);
        }
    }
}

以上兩種寫法我都有放到專案中,你可以看到左方塊可以斜走、右方塊不行,所以第一種的寫法較適合移動控制。

完成專案 Github:tedliou/NewInputSystem_Tutorial

在〈[Unity] 新版 Input System 基礎用法教學 – WASD 移動物件(可斜走)〉中有 1 則留言

發佈留言