Unity 学习笔记-2D游戏

254 阅读6分钟

输入设置

Project Setting - Input Manager

改变对象位置

强制改变

void Update()
{
    // 得到输入值
    float h = Input.GetAxis("Horizontal");
    float v = Input.GetAxis("Vertical");
  
    // 移动对象
    Vector2 pos = transform.position;
    pos.x += speed * h * Time.deltaTime;
    pos.y += speed * v * Time.deltaTime;
    transform.position = pos;
    // 移动对象的另一种方法
    // transform.Translate(
    //  speed * h * Time.deltaTime,
    //  speed * v * Time.deltaTime,
    //  Space.Self
    // );
}

问题:

  • 如果使用了物理引擎碰到障碍物的话,会有抖动问题

使用刚体来改变(解决上面的抖动问题)

void Awake()
{
    rigidbody = GetComponent<Rigidbody2D>();
}

void Update()
{
    ...
    // transform.position = pos;
    rigidbody.MovePosition(pos);
}

挂载物理组件

刚体(Rigidbody 2D)

  • 不需要重力(俯视,跑大地图)的话,将Gravity Scale设为0
  • 想固定角度的话,勾选上Constraints中的Freeze Rotation

碰撞器(XXX Collider 2D)

自动渲染深度

近的覆盖远的,即Y坐标越小,越后渲染

Project Setting - Graphics

Transparency Sort Mode 改为 Custom Axis,下面的Axis改为X:0 Y:1 Z:0

image_EY0B3F38-2.png

效果(运行时也一样):

gif-2024-11-20 at 17.41.03_Bd6AAkpvg5.gif

添加动画管理(基于新版Animator)

原理

  • 使用Animator组件可将动画分配给游戏对象。Animator 组件需要引用 Animator Controller,后者定义要使用哪些动画剪辑(Animation),并控制何时以及如何在动画剪辑之间进行混合和过渡。
  • 即一个游戏对象,可以切换不同的Animator Controller,实现不同的动画播放策略

步骤

  1. 挂载Animator组件:
    • 给挂载了Sprite Renderer的游戏对象添加Animator组件
  2. 创建Animator Controller组件并赋给Animator:
    • Project面板中创建Animator Controller
    • 赋给上面Animator组件的Controller
  3. 创建Animation Clip并添加到Animator Controller中:
    • 选中挂载了Animator的游戏对象
    • 打开Animation面板(⌘6),点击面板中间的Create按钮
    • 选择保存位置然后点确定
    • Project 面板中将动画相关的Sprite拖到Animation面板时间轴上

gif-2024-11-20 at 17.37.03_IiR2JJEKuS.gif

快捷方式

选中动画相关的Sprite,拖放至的游戏对象上,然后确认Animation Controller和Animation Clip的保存位置。编辑器会自动给游戏对象挂载Animator,并关联Animator Controller

gif-2024-11-20 at 17.50.55_s60aIbdU39.gif

动画控制

过渡

  • Has Exit Time:(过渡前动画)是否需要有过渡退出时间
  • Conditions:进行过渡的条件
  • 若想动画马上过渡(按下按键马上切动画)
    • 设置好Contitions
    • 反选Has Exit Time
    • Transition Duration设为0

使用混合树(Blend Tree)对动画进行混合

目的:按下方向键时,角色播放行走动画,释放时回到待机动画

思路:用2个方向参数决定角色方向,用速度参数决定使用待机动画还是行走动画

步骤:

  1. 添加3个参数:XVal、YVal、MoveScale

    image_0CdCbh36Wd.png

  2. 按步骤(混合树(Blend Tree)的应用)添加2个混合树,分别是:

    • 待机(Idle)混合树

      gif-2024-11-21 at 10.48.44_OAdi76en1Q.gif

    • 行走(Walk)混合树

      gif-2024-11-21 at 10.51.54_5Op-zxJEBf.gif

  3. 添加这两个混合树之间的过渡

    • 注意不需要退出时间和过渡时间 image_TkelWEQ2cl.png ⬆️待机到行走(行走到待机同理)
  4. 修改角色脚本

void Update()
{
    // 得到输入值
    // 因不用渐加/减速,所以这里改用 GetAxisRaw 方法
    float h = Input.GetAxisRaw("Horizontal");
    float v = Input.GetAxisRaw("Vertical");
    
    // 移动对象
    Vector2 pos = transform.position;
    pos.x += speed * h * Time.deltaTime;
    pos.y += speed * v * Time.deltaTime;
    rb.MovePosition(pos);
    
    // 设置动画参数
    lookDir.Set(h, v);  // 新增的私有变量 lookDir
    animator.SetFloat("XVal", h);
    animator.SetFloat("YVal", v);
    animator.SetFloat("MoveScale", lookDir.normalized.magnitude);
}

效果

gif-2024-11-21 at 11.15.52_c71AUEpxBF.gif

问题:释放按钮后,角色会自动切到向下的Idle动画,原因是XVal和YVal都是0,混合树中没有匹配条件的动画,就自动使用第一个动画了

image_nzHyR81lo0.png

解决思路:有输入才更新两个方向参数,不然保留之前的

void Update()
{
    // 得到输入值
    ...
    
    // 移动对象
    ...
    
    // 设置动画参数
    float moveScale = 0;
    if (h != 0 || v != 0)
    {
        // 有输入才更新方向和速度
        lookDir.Set(h, v);
        moveScale = 1;
    }
    animator.SetFloat("XVal", lookDir.x);
    animator.SetFloat("YVal", lookDir.y);
    animator.SetFloat("MoveScale", moveScale);
}

效果

gif-2024-11-21 at 11.50.16_5PMM3ltOvZ.gif

又有一个问题:角色的移动速度时快时慢,原因是Update方法的调用频率是当前帧率决定的,那就意味着Time.deltaTime的值会不断变化,导致速度时快时慢。

解决方法:将物理系统相关的更新逻辑放到FixedUpdate方法中。因为FixedUpdate方法是按固定时间间隔来调用的,而物理系统默认也是按照固定时间步长来更新,所以这方法适合用于处理物理相关的更新。

void Update()
{
    // 得到输入值
    ...
    // 设置动画参数
    moveScale = 0;  // 改声明为私有变量,因为要给FixedUpdate使用
    if (h != 0 || v != 0)
    {
        lookDir.Set(h, v);
        moveScale = 1;
    }
    animator.SetFloat("XVal", lookDir.x);
    animator.SetFloat("YVal", lookDir.y);
    animator.SetFloat("MoveScale", moveScale);
}

void FixedUpdate()
{
    // 移动对象部分移到这
    Vector2 pos = transform.position;
    pos += speed * moveScale * lookDir * Time.fixedDeltaTime;  // 注意改为了 fixedDeltaTime
    rb.MovePosition(pos);
}

gif-2024-11-21 at 12.13.46_vUo5ihqmep.gif

更进一步,跑起来

需求:

  • 快速按下2次同样的方向键(第二次按住不放),激活跑步,移动速度加倍
  • 跑步状态下可改变方向
  • 没方向输入后,跑步状态解除

思路:

image_9ts9NY5PEM.png

  • 当动画状态由待机切到行走时(即按下方向键)
    • 记录行走方向
    • 记录开始行走时间
    • 若之前已有记录行走方向且与当前的一样,且当前时间与上次行走结束时间之差在一定范围内,则判定为激活了奔跑状态
  • 当动画状态从行走切回待机时(即释放方向键)
    • 首次按下释放不能太慢,所以想得到有效的首次释放时间,条件是当前时间与开始行走时间之差在一定范围内,记录此时间为上次行走结束时间
  • 当动画状态从跑步切回待机时(也是释放方向键)
    • 有可能正在转向,中间会有个没有方向输入的过程,不能判定为解除了奔跑状态
    • 所以在一定时间后如果状态还是待机的话,则判定为解除了奔跑状态
  • 其他
    • 支持所有方向按钮的输入,所以不能将按键判断逻辑写死

TileMap

创建图层至涂刷地面

创建TileMap图层

在层级面板中右键创建图层

image.png

命名为 Ground

image.png

创建新调色板然后新增图块

在 Tile 调色板面板中创建新调色板

image.png

命名好点创建

image.png

调色板保存路径自行选择(我用 Assets/Art/Tilemap),调色板配置文件就会保存到该目录下

image.png

将图片拖到调色板中,以新增图块

image.png

释放鼠标后会确认保存位置(还是使用上次的路径吧),确认好命名然后点保存即可。图块新增成功

image.png

使用刚新增的图块涂刷 Ground 图层

  1. 在调色板面板中确认选中的图层是 Ground(暂时只有这个)
  2. 选中要涂刷的图块
  3. 点击涂刷工具

image.png

鼠标移到场景面板中按需涂刷

image.png