Unity基础笔记(2)—— Untiy2D及输入系统
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;
}
}
三、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);
}
}
四、2D 物理系统:碰撞体
1. 碰撞体概念
碰撞体:指游戏中一个游戏物体的物理边缘,用来防止穿模、检测碰撞。
2. 碰撞体组件
在Inspector面板中点击 Edit Collider,可以在 Scene 面板中编辑碰撞体尺寸。
- Offset:偏移量
- Size:碰撞体尺寸
- Material:物理材质
3. 碰撞事件
很多时候,我们需要知道两个游戏物体发生碰撞产生的结果,比如车辆碰撞等。
- OnCollisionEnter2D:碰撞进入,使用较多
- OnCollisionExit2D:碰撞退出
- OnCollisionStay2D:碰撞过程中
- Collision2D:碰撞信息
- gameObject:对方的游戏物体
- transform
如何进入碰撞事件?
- 双方都没有碰撞体和刚体,绝对不可能触发碰撞事件(函数)。
- 双方都有碰撞体和刚体,可以触发碰撞事件。
- 双方都有碰撞体,但只有一方有刚体,也可以触发碰撞事件(无论哪一方有刚体,都可以触发碰撞事件)。
- 双方都有碰撞体,但都没有刚体,不能触发碰撞事件。
碰撞事件代码示例:
// 碰撞进入
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("碰撞过程中");
}
五、2D 物理系统:触发
1. 触发概念
很多时候我们并不需要游戏物体发生碰撞,比如赛车游戏中,我们需要知道什么时候玩家到达了终点,用来作为胜利或计时的依据。或者传送门,玩家进入后可以传送,但这些游戏物体并不需要真的和玩家发生碰撞。
2. 设置触发
设置触发只需要在碰撞体上勾选 IsTrigger 即可。
注意:设置触发后这个游戏物体并不具备 “物理边缘” ,任何游戏物体都可以穿过它。
3. 触发事件
触发事件一般用于判断两个物体是否发生了碰撞交互,但不必有物理碰撞效果,比如通过特定地点触发剧情等。
- OnTriggerEnter2D:触发进入
- OnTriggerExit2D:触发退出
- OnTriggerStay2D:触发过程中,使用较多
- Collider2D:对方碰撞体
如何进入触发事件?
- 双方都没有碰撞体和刚体,绝对不可能发生触发事件(函数)。
- 双方都有碰撞体和刚体,可以发生触发事件。
- 双方都有碰撞体,但只有一方有刚体,也可以发生触发事件(无论哪一方有刚体,都可以发生触发事件)。
- 双方都有碰撞体,但都没有刚体,不能发生触发事件。
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
}
}
三、鼠标输入
鼠标输入检测
鼠标输入的几种情况:
- 鼠标按下:
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);
}
}
}
四、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,0,1
Input.GetAxisRaw("Horizontal");
没有输入时默认为0,有输入时:
- 若为平滑过渡,按负向按钮就会从0一直过渡到-1,按正向按钮会从0过渡到1.
- 若为GetAxisRaw,按负向按钮就是-1,按正向按钮就是1.
获取鼠标滚轮的输入:
// 向上滑滚轮为正,向下为负
float wheel = Input.GetAxis("Mouse ScrollWheel");
五、案例
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);
}
}
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;
}
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤