教程来源:B 站 Up 主的课程:Unity教程 入门第一款游戏制作

以下都是基于 2D 游戏

常用操作

通用操作

游戏状态进行保存

在游戏运行时修改 Inspector 中组件的参数,点击组件右上角,选择 Copy Componpent,

游戏运行结束后,点击组件右上角,选择 Paste Component Values,可以实现保存运行时的参数

使用 TileMap 绘制地图

TileMap 创建:Hirerachy > 右键 > 2D Object > TileMap

创建调色板:Window > 2D > Tile Palette

  • 将图片拖到调色板中即可变成 Tile 文件,然后可以用调色板的工具绘制地图

  • Tile 文件可以存在 Environment 下新建一个 map 目录

每单位像素数 (Pixels Per Unit):选中精灵资源在 Inspetor 面板里会看到,表示在一个 Unity 单位中一行或一列有几个像素点

  • 如果瓦片拖到界面上后,瓦片之前有间距,可以调整这个参数

切割图集:选中一张精灵图片资源,将 SpriteMode 从 single 改为 mutiple,可制作成图集,再点击 SpriteEditor 可进行切割。

切割有三种形式:自动,按像素切割,按行列切割

  • 对于一张比较大的精灵图,我们拖到 Scene 上看似占用比较大的空间,其实只占用了一个格子,为了让它的实际占用很看起来一样大,需要将这张图切割成图集
  • 对于这种看似比较大的图片,使用按行列切割,切割成一个个小格子

实现碰撞体效果

Rigidbody:刚体组件,使游戏物体能获得重力,接受外界的受力和扭力功能的组件

BoxCollider:碰撞器组件,使游戏物体具有跟挂载刚体组件的游戏物体发生碰撞能力的组件

实现碰撞效果:给人物添加 Rigidbody 2D 和 Box Collider 2D 组件,给 Tilemap 添加 Tilemap Collider 2D 组件

不允许旋转效果:Rigidbody 2D > Constraints > Freeze Rotation

移动 Bug 的修复

如果给整个人物添加方形的 Collider,移动时会卡住,解决方案是下半身使用圆形的 Collider

实现人物控制

输入按键设置:Edit > Project Settings > Input Manager,这里可以更改各个轴向映射的按键

GetAxis获取 [-1, 0], [0, 1] 之间的小数:

float horizontalMove = Input.GetAxis("Horizontal");

GetAxisRaw 获取的是 -1, 0, 1 中的某个值

float faceDirection = Input.GetAxisRaw("Horizontal");

GetButton 可以检测到用户按下某个功能键,如 Jump - 跳跃

if (Input.GetButton("Jump"))
{
  rb.velocity = new Vector2(rb.velocity.x, jumpForce * Time.deltaTime);
}

动画系统

打开动画面板:Window -> Animation -> Animation

  • 动画面板用于制作动画,将一系列图片拖进去做出动画效果

打开动画器面板:Window -> Animation -> Animator

  • 动画器面板用于关联各个动画之间的状态转换

添加动画效果

1、给游戏组件添加 Animator 组件

2、创建一个存放动画的文件夹,在文件夹里创建一个 Animator Controller,用于控制动画

3、将 Animator Controller 拖到 Animator 组件上

4、选中游戏组件,在动画面板,创建一个 idle 动画,并将动画图片拖入

实现跑动动画

1、创建一个 run 动画

2、在动画器面板,run 和 idle 之间创建过渡(make transition)

3、Parameters 中添加参数 running,float 类型

4、idle -> running 的过渡,将 Has Exit Time 去掉,Transition Offset 设为 0,Conditions 为 running > 0.1

running -> idle 同理,Conditions 为 running < 0.1

5、根据上面给过渡设置的 Conditions,在代码中用 animator.SetFloat() 给 running 赋值,来控制跑动动画

实现跳跃和降落动画

1、创建 jump 动画、fall 动画

2、在动画器面板,各个动画之间创建过渡(make transition)

3、Parameters 添加参数 jumpingfalling,Bool 类型

4、过渡的 Inspector 中,将 Has Exit Time 去掉,Transition Offset 设为 0

往 jump 过渡的 Conditions 为 jumping = true;往 fall 过渡的 Conditions 为 falling = true

5、根据 Conditions,编写代码

public Rigidbody2D rb; // 刚体
public BoxCollider2D coll; // 碰撞体
public Animator animator; // 动画器
public LayerMask ground; // 地面图层

...

// 检查并切换动画状态
void SwitchAnim()
{
  // 处于跳跃状态
  if (animator.GetBool("jumping"))
  {
    // y轴的力没有了
    if (rb.velocity.y < 0)
    {
      animator.SetBool("jumping", false);
      animator.SetBool("falling", true);
    }
  }
  // 处于降落状态, 碰撞了地面
  else if (coll.IsTouchingLayers(ground))
  {
    animator.SetBool("falling", false);
    animator.SetBool("idle", true);
  }
}

6、代码中的 public LayerMask ground 指的就是游戏物件所处的图层:

为了实现检测碰撞地面,需要给 Tilemap 设置一个图层 Group,并在代码中获取:

镜头控制

脚本控制

这个方法就是给 Main Camera 添加一个脚本,让它的 Transform 的 x、y 时刻与 player 保持一致即可

关于 y 是否需要保持一致主要看游戏需求,例如超级马里奥跳起来镜头不会动,恶魔城跳起来镜头就会跟随

public class CameraController : MonoBehaviour
{
    public Transform player;

    void Update()
    {
        transform.position = new Vector3(player.position.x, 0, -10f);
    }
}

Cinemachine

首先在 Package Manager 中安装 Cinemachine,然后顶部菜单会多一个 Cinemachine

背景跟随

1、Cinemachine > Create 2D Cinemachine,创建一个 CM vcam 1 对象

2、将要跟随的游戏对象拖到 CM vcam 1 > Inspector 中的 Follow

Inspector 中的一些参数:

  • Lens > Orthographic Size:调整镜头大小

  • Body > Dead Zone:镜头不会跟随的一段区域,超出这个区域则会自动跟随

给背景限定区域

  • CM vcam 1 > Inspector > Add Extension > Cinemachine Confiner

  • 需要给上面的组件指定一个 Collider,给 Background 添加 Collider(勾选 isTriger)

    这里使用 Polygon Collider

  • CM vcam 1 > Inspector > Cinemachine Confiner > Bounding Shape 2D 指定为 Background 的 Collider

添加物品

在界面上添加游戏物件的方法

  • 创建一个 Sprites,将物品素材拖给它,记得修改对应的层级

给物品添加的动画效果

  • 给物体添加 Animator 组件,在文件夹中创建一个 Animate Controller 并拖到物体身上的 Animator 中
  • 在动画面板中创建动画效果

给物品添加碰撞销毁事件

  • 给物品添加 Box Collider 2D 组件,并勾选的 isTrigger

    不勾选 isTrigger 则像墙一样撞不动,勾选后可以进行一些触碰事件(配合 OnTriggerEnter2D 函数)

  • 给物体设置 Tag 为 Collection

// 碰撞事件
private void OnTriggerEnter2D(Collider2D collision)
{
  // 如果碰撞到的物体标签是Collection,则销毁
  if (collision.CompareTag("Collection"))
  {
    Destroy(collision.gameObject);
  }
}

制作预制体

创建一个 Prefabs 文件夹,将做好的 Cherry 物品拖到该文件夹中,后面就做好的物品为模版,反复创建其他物品(功能相同)

如果不使用 Prefabs,则每次新增一个物品都需要反复执行大量重复操作,有 Prefabs 只需要复制即可

代码理解

Time.deltaTime 代表两帧之间的时间差。

  • 脚本中的 update() 方法虽然是每帧运行,但实际运行时两帧之间的时间间隔不一定相等。

对于 Rigidbody、Collider 这种,几乎每个游戏物件身上挂载后是不会变的,因此可以不声明为 pubilc,再通过 Unity 中拖拽赋值,

可以直接声明为 private,并在代码中赋值。

[SerializeField] 可以使得 private 变量也显示在 Unity 中。

[SerializeField] private Rigidbody2D rb;
Logo

助力合肥开发者学习交流的技术社区,不定期举办线上线下活动,欢迎大家的加入

更多推荐