Menu
CoddyTech

输入操作

本课属于 Coddy Unity 学习旅程的“打造真正的游戏”单元。第 47 课,共 60 课。

逐个检测按键会让脚本依赖键盘。动作代表玩家要做的事,而项目会列出触发该动作的按键、摇杆和按钮。新的 Unity 6 项目自带一组动作(InputSystem_Actions 资源,设为整个项目共用的动作),其中 Player 映射包含 Move(WASD、方向键和游戏手柄的左摇杆)、Look(鼠标或右摇杆)、Attack(鼠标左键和 Enter)、Interact(按住 E)、Crouch(C)、Jump(空格键和游戏手柄的南键)、Previous 和 Next(1 和 2),以及 Sprint(左 Shift)。这些动作从一开始就已启用,可以通过名称用 InputSystem.actions.FindAction("Jump") 获取。这个横向视角的抓娃娃机在 x 轴和 y 轴上移动,并在按下 Jump 时抓取物品:

using UnityEngine;
using UnityEngine.InputSystem;

public class ClawCrane : MonoBehaviour
{
    public float speed = 3f;

    private InputAction moveAction;
    private InputAction jumpAction;

    void Start()
    {
        moveAction = InputSystem.actions.FindAction("Move");
        jumpAction = InputSystem.actions.FindAction("Jump");
    }

    void Update()
    {
        Vector2 input = moveAction.ReadValue<Vector2>();
        transform.position += new Vector3(input.x, input.y, 0f) * speed * Time.deltaTime;

        if (jumpAction.WasPressedThisFrame())
            Debug.Log("Grab!");
    }
}

动作只在 Start 中查找一次,并保存在 InputAction 字段中。Move 会提供一个 Vector2:x 表示左右方向,y 表示按键控制的上下方向,而且结果会经过归一化,因此同时按下 W 和 D 得到的是 (0.71, 0.71),而不是 (1, 1)。这是横向视角,所以抓娃娃机会用 y 表示高度;俯视角游戏则会用它表示 z。按钮动作的响应方式和按键一样:WasPressedThisFrame()、WasReleasedThisFrame() 和 IsPressed()。两种错误会导致异常:名称拼错时,FindAction 会返回 null(首次读取时会出现 NullReferenceException);对 Move 调用 ReadValue<Vector3>() 时,只要按住一个按键就会抛出 InvalidOperationException,因为 Move 使用的是 Vector2。

challenge icon

挑战

中等

使用项目中的操作来移动测量员并插旗。

  1. 在 Start() 中,使用 InputSystem.actions.FindAction("Move")、"Jump" 和 "Attack" 设置 moveAction、jumpAction 和 attackAction。
  2. 在 Update() 中,通过 moveAction.ReadValue<Vector2>() 乘以 speed 来移动,y 分量沿 z 轴移动。
  3. 当 jumpAction.WasPressedThisFrame() 时调用 Plant(),按下 Attack 时调用 PullUp()。

点击 开始,插下三面旗子,然后点击拔起一面。接着点击 检查。

亲手试试

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;

public class Surveyor : MonoBehaviour
{
    public float speed = 4f;
    public int flags = 3;
    public GameObject flagPrefab;

    private InputAction moveAction;
    private InputAction jumpAction;
    private InputAction attackAction;
    private List<GameObject> planted = new List<GameObject>();

    void Start()
    {
        // 找到 Move、Jump 和 Attack 操作
    }

    void Update()
    {
        // 用 Move 行走,按下 Jump 时调用 Plant(),按下 Attack 时调用 PullUp()
    }

    void Plant()
    {
        if (flags == 0) return;
        Vector3 spot = new Vector3(transform.position.x, 0.75f, transform.position.z);
        planted.Add(Instantiate(flagPrefab, spot, Quaternion.identity));
        flags--;
        Debug.Log("Flags left: " + flags);
    }

    void PullUp()
    {
        if (planted.Count == 0) return;
        GameObject last = planted[planted.Count - 1];
        planted.RemoveAt(planted.Count - 1);
        Destroy(last);
        flags++;
        Debug.Log("Flags left: " + flags);
    }
}

打造真正的游戏中的所有课

自己练习: Unity 在线编辑器