当前位置:   article > 正文

Unity基础笔记(2)—— Unity2D及输入系统_unity 键盘输入

unity 键盘输入

Unity2D及输入系统

Unity2D 部分

一、Unity 2D 介绍

1. 游戏中 2D、3D 以及 UI 的概念

先笼统地将整个游戏分为两部分:UI 和游戏内容。

  • UI :即 User Interface,人机交互,操作界面,游戏中一般指血条、背包、注册登录等。

  • 游戏内容:指场景、角色等实际游戏世界的展示。

    一般我们所说的 2D/3D 是指游戏内容部分,绝大多数情况下 UI 本身都是 2D的。

2. Unity 2D 主要学习内容

(1)2D 素材和 2D 的渲染

(2)2D 物理系统

二、Unity2D 核心部分:Sprite 和 SpriteRenderer

1. 2D 游戏相机

2D相机调整:

  • Projection 设置为 Orthographic 即可,也就是正交模式(忽视距离,失去近大远小的3D特征)
2. Sprite 和 SpriteSheet
  • Sprite:是一种游戏资源,在 2D 游戏中表示角色、场景的图片资源(类似3D中 GameObject);
  • SpriteSheet:切割一个图片为多个 Sprite,就是 SpriteSheet.

美术资源,在 Inspector 面板中的 Texture Type 属性选择**Sprite(2D and UI)**后,就可以正常使用。(scene面板可点击2D切换至2D开发视角)

Pixels Per Unit 属性:控制精灵sprite的比例,数值越大,精灵越小,精度越高。

Sprite Mode:精灵的模式

  • Single:精灵为单个类型,无需切割操作

  • Multiple:精灵是多个类型,可通过 Sprite Editor 对精灵进行切割 Slice操作。

  • Polygon

Sprite Editor:精灵编辑器,需安装2D Sprite包才能使用。

  • Slice 切割操作:Automatic 自动分析像素切割精灵,Grid By Cell Size 根据网格大小等比切割,Grid By Cell Count 根据网格数量进行切割(不会切割没有像素的地方)

一般通过切割精灵自动生成 Sprite Sheets 精灵集。

  • Pivot 中心点,在2D中中心点很重要,它决定了图片以什么样的方式去展示。中心点不一样会产生偏移。
3. SpriteRenderer 组件

SpriteRenderer 组件是一个用来显示 Sprite 的组件。

  • Sprite:表示当前显示的 Sprite;
  • Color:给 Sprite 叠加的颜色;
  • Flip:翻转,X左右翻转,Y上下翻转;
  • SortingLayer:排序层,用来区分2D游戏中不同精灵的图层序列,在下方的优先级更高;
  • OrderinLayer:排序值,控制同层精灵的层次。
public class SpriteDemo : MonoBehaviour
{
    private Spriterenderer spriteRenderer;
    public Sprite sprite;
    
    void Start()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
        spriteRenderer.sprite = sprite;
        spriteRenderer.color = new Color.black;
        spriteRenderer.flipX = true;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

三、2D 物理系统:刚体

1. 物理系统

Unity 的物理系统主要是对现实中的物理现象进行模拟,如重力等。

物理系统常用组件主要由 刚体碰撞体 组成。

2. 2D 刚体

一个游戏如果希望具备重力,那么它一定需要有 RigidBody(刚体)组件。

Rigidbody 2D组件的属性:
BodyType

  • Dynamic:动态,最仿真的。

  • Kinematic:运动,完全由代码控制。

  • Static:静态,不是为了移动而设计的,例如建筑物。

Simulated:是否模拟,不模拟的话,不会有重力、碰撞等。

Mass:质量。

Linear Drag:位置移动的阻力系数。

Angular Drag:旋转移动的阻力系数。

Gravity Scale:重力系数。

Collision Detection:碰撞检测,定义如何检测 2D 碰撞体之间的碰撞。

  • Discrete:如果物体移动过快,两物体可以重叠或穿过彼此。
  • Continuous:具有2D刚体和2D碰撞体的游戏对象在物理更新时不会穿过彼此,但比Discrete更耗费CPU时间。

Constraints:定义对 2D 刚体运动的任何限制。

  • Freeze Position:分X和Y,用于固定X轴或Y轴的位置。
  • Freeze Rotation:用于固定物体旋转,例如角色站在边缘上不能让它受重力控制旋转。

​ 如果精灵Sprite需要运动就需要加刚体组件,但刚体组件只注重物体本身的物理特性,它不管物体周边的碰撞效果,要想让一个物体与其他物体接触需要使用碰撞体组件。

3. 物理材质

物理材质是一种资源,分为以下两个部分:

  • Friction:用于设置摩擦力大小。
  • Bounciness:用于设置弹性大小。
// 刚体组件示例代码
public class RigidbodyDemo : MonoBehaviour
{
    private Rigidbody2D rigidbody2D;
    void Start()
    {
        rigidbody2D = GetComponent<Rigidbody2D>();
        rigidbody2D.mass = 3;
        rigidbody2D.gravityScale = 0.5f;
    }
    void Update()
    {
        // 向指定坐标移动
        rigidbody2D.MovePosition(new Vector2(0, 1) * 10);
        // 向指定方向一直移动
        rigidbody2D.MovePosition(transform.position + new Vector3(0, 1, 0) * Time.deltaTime);
        // 改变速度向量,即施加一个任意方向任意大小的速度
        rigidbody2D.velocity = new Vector2(0, 1);
        // 对刚体施加力
        rigidbody2D.AddForce(Vector2.up);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

四、2D 物理系统:碰撞体

1. 碰撞体概念

碰撞体:指游戏中一个游戏物体的物理边缘,用来防止穿模、检测碰撞

2. 碰撞体组件

在Inspector面板中点击 Edit Collider,可以在 Scene 面板中编辑碰撞体尺寸。

  • Offset:偏移量
  • Size:碰撞体尺寸
  • Material:物理材质
3. 碰撞事件

很多时候,我们需要知道两个游戏物体发生碰撞产生的结果,比如车辆碰撞等。

  • OnCollisionEnter2D:碰撞进入,使用较多
  • OnCollisionExit2D:碰撞退出
  • OnCollisionStay2D:碰撞过程中
  • Collision2D:碰撞信息
    • gameObject:对方的游戏物体
    • transform

如何进入碰撞事件?

  1. 双方都没有碰撞体和刚体,绝对不可能触发碰撞事件(函数)
  2. 双方都有碰撞体和刚体,可以触发碰撞事件。
  3. 双方都有碰撞体,但只有一方有刚体,也可以触发碰撞事件(无论哪一方有刚体,都可以触发碰撞事件)。
  4. 双方都有碰撞体,但都没有刚体,不能触发碰撞事件

碰撞事件代码示例:

// 碰撞进入
private void OnCollisionEnter2D(Collision2D collision)
{
    // print("碰撞进入,碰撞的物体是:" + collision.gameObject.name);
    // 如果碰撞的物体的球,就表示被击中并销毁游戏物体
    if(collision.gameObject.name == "Circle")
    {
        print("被击中");
        GameObject.Destroy(collision.gameObject);
    }
}
// 碰撞退出
private void OnCollisionExit2D(Collision2D collision)
{
    print("碰撞退出");
}
// 碰撞中
private void OnCollisionStay2D(Collision2D collision)
{
    print("碰撞过程中");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

五、2D 物理系统:触发

1. 触发概念

​ 很多时候我们并不需要游戏物体发生碰撞,比如赛车游戏中,我们需要知道什么时候玩家到达了终点,用来作为胜利或计时的依据。或者传送门,玩家进入后可以传送,但这些游戏物体并不需要真的和玩家发生碰撞

2. 设置触发

设置触发只需要在碰撞体上勾选 IsTrigger 即可。

注意:设置触发后这个游戏物体并不具备 “物理边缘” ,任何游戏物体都可以穿过它。

3. 触发事件

触发事件一般用于判断两个物体是否发生了碰撞交互,但不必有物理碰撞效果,比如通过特定地点触发剧情等。

  • **OnTriggerEnter2D:**触发进入
  • **OnTriggerExit2D:**触发退出
  • **OnTriggerStay2D:**触发过程中,使用较多
  • **Collider2D:**对方碰撞体

如何进入触发事件?

  1. 双方都没有碰撞体和刚体,绝对不可能发生触发事件(函数)
  2. 双方都有碰撞体和刚体,可以发生触发事件。
  3. 双方都有碰撞体,但只有一方有刚体,也可以发生触发事件(无论哪一方有刚体,都可以发生触发事件)。
  4. 双方都有碰撞体,但都没有刚体,不能发生触发事件

Unity 输入系统部分

一、游戏输入介绍

1. 游戏输入概念

游戏中的输入,就是指玩家的键盘按键、鼠标点击等行为。

一般会触发一些游戏行为,比如打开背包、角色移动等,其目的是为了让玩家交互。

2. 游戏输入场景

PC端:基于键盘、鼠标、摇杆等硬件输入;

平板/手机:基于屏幕输入,游戏中实际响应的多为UI元素;

主机/其他:基于手柄、摇杆;

VR:基于VR眼镜、VR手柄等。

二、键盘输入

键盘输入检测

键盘输入的几种情况

  • 键盘按下:Input.GetKeyDown(KeyCode.A)
  • 按键弹起:Input.GetKeyUp(KeyCode.A)
  • 键盘按下持续中:Input.GetKey(KeyCode.A)

Input 方法示例:

public class KeyboardDemo : MonoBehaviour
{
    private float attackValue = 0;
    void Update()
    {
        #region 按键检测

        // 按下
        // 只有第一次按下的那一帧有效
        if (Input.GetKeyDown(KeyCode.A))
        {
            print("A");
        }

        // 弹起
        // 只有第一次按下的那一帧有效
        if (Input.GetKeyUp(KeyCode.W))
        {
            print("W");
        }

        // 按下中
        // 在按下的过程中持续生效,每一帧都生效
        if (Input.GetKey(KeyCode.S))
        {
            print("S");
        }

        // 蓄力:按下->按住->弹起
        if(Input.GetKeyDown(KeyCode.J))
        {
            print("开始蓄力");
            attackValue = 0;
        }
        if(Input.GetKey(KeyCode.J))
        {
            print("蓄力中");
            attackValue += Time.deltaTime;
        }
        if(Input.GetKeyUp(KeyCode.J))
        {
            print("蓄力结束,攻击力为 " + attackValue);
        }

        #endregion
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

三、鼠标输入

鼠标输入检测

鼠标输入的几种情况:

  • 鼠标按下:Input.GetMouseButtonDown(0);
  • 鼠标抬起:Input.GetMouseButtonUp(0);
  • 鼠标持续按下中:Input.GetMouseButton(0);
  • 鼠标当前坐标:Input.mousePosition

0 代表鼠标左键,1 代表鼠标右键

鼠标输入示例:

public class MouseDemo : MonoBehaviour
{
   void Update()
   {
       // 0:左键,1:右键
       if(Input.GetMouseButtonDown(0))
       {
           print("鼠标左键点击");
       }

       if(Input.GetMouseButtonUp(0))
       {
           print("鼠标左键弹起");
       }

       if(Input.GetMouseButton(0))
       {
           print("鼠标左键持续按下");
       }

       // 鼠标位置
       // 并不是游戏中的位置
       // 而是以左下角为原点,横轴为屏幕宽度,纵轴为屏幕高度的平面直角坐标系
       if (Input.GetMouseButtonDown(1))
       {
           print(Input.mousePosition);

       }
   }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

四、InputManager 详解

1. InputManager 介绍

InputManager 是 Unity 为开发者提供好的一个输入管理器,我们之前使用的鼠标、键盘检测,实际上都和这个脱离不了关系。

进入路径:Edit->ProjectSettings->InputManager

2. 设置参数
  • **Name:【轴的名称】可以在脚本编程中直接引用它。**例如:Input.GetAxis("Horizontal")
  • Nagative Button:【负向按钮】该按钮会给轴发送一个负值。
  • Positive Button:【正向按钮】该按钮会给轴发送一个正值。
  • Gravity:【重力】输入复位的速度,仅用于 按键/鼠标。
  • Dead:【一个阈值】任何小于该值的输入值(不论正负)都会被视为0,用于摇杆。
  • Sensitivity:【灵敏度】对于键盘输入,该值越大则响应时间越快,该值越小则越平滑。对于鼠标输入,设置该值会对鼠标的实际移动距离按比例缩放。
  • Snap:【对齐】如果启用该设置,当轴收到反向的输入信号时,轴的数值会立即置为 0,仅用于 按键/鼠标 输入。
  • Invert:【反转】启用该参数可以让正向按钮发送负值,反向发送正值。
  • Type【类型】
  • Axis:【轴】设备的输入轴(摇杆、鼠标、手柄等)。
  • JoyNum:【摇杆编号】设置使用哪个摇杆。默认是接收所有摇杆的驶入。仅用于输入轴和非按键。
3. 主要使用方法
// 有平滑过渡
Input.GetAxis("Horizontal");
  • 1
  • 2
// 只能是 -1,0,1
Input.GetAxisRaw("Horizontal");
  • 1
  • 2

没有输入时默认为0,有输入时:

  • 若为平滑过渡,按负向按钮就会从0一直过渡到-1,按正向按钮会从0过渡到1.
  • 若为GetAxisRaw,按负向按钮就是-1,按正向按钮就是1.

获取鼠标滚轮的输入:

// 向上滑滚轮为正,向下为负
float wheel = Input.GetAxis("Mouse ScrollWheel");
  • 1
  • 2

五、案例

1. 小球移动

(1)案例介绍

让小球可以在平台上可以左右移动即可,A:向左移动,D:向右移动。

(2)案例实现

public class CircleMove : MonoBehaviour
{
    // 每秒移动多少米(常规情况)
    public float Speed = 1;

    // 帧更新
    void Update()
    {
        // 移动
        Move();
    }

    /// <summary>
    /// 移动
    /// </summary>
    void Move()
    {
        // 获取玩家输入状况
        float horizontal = Input.GetAxis("Horizontal");
        //float vertical = Input.GetAxis("Vertical");
        // 根据输入得到移动方向
        Vector3 dir = new Vector3(horizontal, 0, 0);
        // 根据移动方向进行移动,帧率越高 需要 单帧移动速度越低
        transform.Translate(dir * Time.deltaTime * Speed);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
2. 小球跳跃

(1)功能介绍

基于移动的基础上,补充跳跃功能:a. 按空格后小球会跳起来,b. 落地会出现一定的回弹。

(2)功能实现

public class CircleJump : MonoBehaviour
{
    // 跳跃基于刚体运动
    private new Rigidbody2D rigidbody2D;
    // 跳跃给一个向上的力
    public float JumpPower = 10;
    // 是否在地面上
    private bool isOnGround = true;

    // 在Start()中初始化
    private void Start()
    {
        rigidbody2D = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        // 跳跃
        Jump();
    }

    /// <summary>
    /// 跳跃
    /// </summary>
    void Jump()
    {
        // 如果按空格且在地面上就跳跃
        // 防止跳跃给的力可以在空中进行而导致飞天
        if (Input.GetKeyDown(KeyCode.Space) && isOnGround)
        {
            // 因为跳跃是一瞬间执行的和持续性的移动不同
            // 所以不用 Time.deltaTime
            rigidbody2D.AddForce(Vector2.up * JumpPower);
        }
    }

    // 碰撞进入
    private void OnCollisionEnter2D(Collision2D collision)
    {
        // 判断是否接触了地面
        if(collision.gameObject.tag == "Floor")
        {
            isOnGround = true;
        }
    }

    // 碰撞退出
    private void OnCollisionExit2D(Collision2D collision)
    {
        // 判断是否离开地面
        if (collision.gameObject.tag == "Floor")
        {
            isOnGround = false;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/106626
推荐阅读
相关标签
  

闽ICP备14008679号