【第二节课后练习解析】

public class Class2_CubeRot_answer : MonoBehaviour
{
    // 速率控制
    // 使用 Public 公开的基础变量可以在检查器面板上控制
    public float Rate = 20f;


    // 类变量,存储要转动的物体
    private GameObject Cube;


    private void Awake()
    {
        // 唤醒时获取要转动的物体
        // this.gameObject => 脚本挂载的物体
        Cube = this.gameObject;
    }

    void FixedUpdate()
    {
        // 在每一帧旋转物体
        // Time.deltaTime => 距离上一帧经过的时间
        // 每秒旋转 * 这两帧经过多少秒(Time.deltaTime) => 这一帧要转多大
        Cube.transform.eulerAngles += new Vector3(0, Rate, 0) * Time.deltaTime;

        // 在 Rate 前加上一个 “-” 表示向相反方向转动
        // Cube.transform.eulerAngles += new Vector3(0, -Rate, 0) * Time.deltaTime;
    }
}

【前置知识点】

C# 判断 - 多态性:C# 判断 | 菜鸟教程

新老输入系统简要介绍

Unity 常用的输入系统分为 (老)InputManager 和  (新)InputSystem。

        老系统功能比较简单,可在下图位置看到详细配置,需通过 Input.Get 系列API主动的获取按键状态,新增修改按键与实现多人游戏时较为麻烦。

        新系统功能比较齐全,需手动从包管理器获取(见下图1),可通过配置 InputActions 的形式实现在 手柄,键盘,鼠标 等不同输入下的适配(见下图2),功能齐全但实现起来较为复杂。

老输入系统读取键盘输入

新输入系统讲解起来有点复杂了,我们在本次课程中还是先使用老输入系统实现。

我们先来看一下输入管理器中的预设,在默认情况下输入管理器给我们提供了 “水平” 和 “垂直” 两个轴的预设:

为了理解 输入轴 这个概念,我们做以下图:

假设我们有两个人在抢一个小球,他们分别站在两边,用两个绳子分别拉着小球:

这时倘若我们把 左边的人所在位置定为 -1右边的人所在位置定为 1 球初始所在位置定为 0 ,并以此做一个数轴,就可以通过数轴描述最终球的位置

回到 输入管理器中的预设 点开任意一个轴预设可以看到,有 肯定按钮,否定按钮 和对应的 Alt:

肯定按钮就相当于站在 1位置 上的人,如果只按下肯定按钮 小球就会向 1位置 移动,获取到轴的值也就趋近于 1

否定按钮就相当于站在 -1位置 上的人,如果只按下否定按钮 小球就会向 -1位置 移动,获取到轴的值也就趋近于 -1

对应的Alt按钮就相当于 对应人的 一个别名,同时按下 肯定按钮 和 Alt肯定按钮 还是一个人拉 因此并不会因此以两倍速度拉向1

接下来我们创建一个 Class3_CubeController 脚本,来到脚本中 我们应该怎么样获取对应轴的值呢?

在 输入管理器对应轴的预设 中有一项属性 “名称”

我们可以通过以下API+名称获取轴的值

Input.GetAxis("轴的名称");

因此我们可以有:

    void Update()
    {
        // 获取 水平 轴的输入
        float hori = Input.GetAxis("Horizontal");
        // 获取 垂直 轴的输入
        float vert = Input.GetAxis("Vertical");
    }

接下来我们像上节课一样 公开一个速度值 并将 水平 & 垂直输入 * 速度 后应用到小方块的位置上:

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

public class Class3_CubeController : MonoBehaviour
{
    public float MoveSpeed = 5f;

    private GameObject Cube;

    private void Awake()
    {
        Cube = this.gameObject;
    }

    void Update()
    {
        // 获取 水平 轴的输入
        float hori = Input.GetAxis("Horizontal");
        // 获取 垂直 轴的输入
        float vert = Input.GetAxis("Vertical");

        // 为什么这里用的是 Time.deltaTime 而 Class2 用的是 Time.fixedDeltaTime 呢?[仅作了解]
        // 因为这里是在 Update (每一渲染帧)中调用,Time.deltaTime 获取的是渲染帧的间隔
        // Class2 的脚本是在 FixedUpdate(每一物理帧)中调用,Time.fixedDeltaTime 获取的是物理帧间隔
        // 获取输入一般在 Update,物理控制一般在 FixedUpdate
        Cube.transform.position += new Vector3(hori, vert, 0).normalized * MoveSpeed * Time.deltaTime;
    }
}

就已经可以 实现读取键盘输入 并控制小方块移动啦!

我们接下来再尝试读取单个按键输入,并实现小方块的冲刺效果

先来梳理一下我们要实现的逻辑:

  1. 当玩家按下 Space键(空格键)的时候触发冲刺
  2. 冲刺的方向 与 当前移动方向一致

读取单个按键我们可以通过以下API实现

Input.GetKeyDown(按键);

因此我们可以通过判断语句实现以下逻辑:

        if (Input.GetKeyDown(KeyCode.Space))
        {
            // 向移动方向冲刺
        }
        else
        {
            // 正常移动
            Cube.transform.position += new Vector3(hori, vert, 0).normalized * MoveSpeed * Time.deltaTime;
        }

那么怎么实现冲刺呢?

我们的冲刺可以看作短时间向移动方向移动很大一段距离?并且好像我们需要控制的是冲刺的距离而不是冲刺的速度?

因此可以通过 当前位置 += 冲刺方向 * 冲刺距离 实现,还是一样我们公开一个变量来控制冲刺距离:

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

public class Class3_CubeController : MonoBehaviour
{
    public float MoveSpeed = 5f; // 移动速度
    public float DashDist = 2f; // 冲刺距离

    private GameObject Cube;

    private void Awake()
    {
        Cube = this.gameObject;
    }


    // 为什么这里用的是 Time.deltaTime 而 Class2 用的是 Time.fixedDeltaTime 呢?[仅作了解]
    // 因为这里是在 Update (每一渲染帧)中调用,Time.deltaTime 获取的是渲染帧的间隔
    // Class2 的脚本是在 FixedUpdate(每一物理帧)中调用,Time.fixedDeltaTime 获取的是物理帧间隔
    // 获取输入一般在 Update,物理控制一般在 FixedUpdate
    void Update()
    {
        // 获取 水平 轴的输入
        float hori = Input.GetAxis("Horizontal");
        // 获取 垂直 轴的输入
        float vert = Input.GetAxis("Vertical");

        if (Input.GetKeyDown(KeyCode.Space))
        {
            // 向移动方向冲刺
            Cube.transform.position += new Vector3(hori, vert, 0).normalized * DashDist;
        }
        else
        {
            // 正常移动
            Cube.transform.position += new Vector3(hori, vert, 0).normalized * MoveSpeed * Time.deltaTime;
            // 这里使用 .normalized 归一化是为了保证向各个方向移动速率一致
        }
    }
}

就已经实现读取键盘输入控制小方块的移动和冲刺啦!

【课后练习】

1、更改冲刺的触发为 LeftShift 键【提交代码文件】

2、(可选)冲刺添加冷却时间(3s)【提交代码文件】

更多推荐