输入设置
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
效果(运行时也一样):
添加动画管理(基于新版Animator)
原理
- 使用Animator组件可将动画分配给游戏对象。Animator 组件需要引用 Animator Controller,后者定义要使用哪些动画剪辑(Animation),并控制何时以及如何在动画剪辑之间进行混合和过渡。
- 即一个游戏对象,可以切换不同的Animator Controller,实现不同的动画播放策略
步骤
- 挂载Animator组件:
- 给挂载了
Sprite Renderer的游戏对象添加Animator组件
- 给挂载了
- 创建Animator Controller组件并赋给Animator:
- 在
Project面板中创建Animator Controller - 赋给上面
Animator组件的Controller项
- 在
- 创建Animation Clip并添加到Animator Controller中:
- 选中挂载了
Animator的游戏对象 - 打开
Animation面板(⌘6),点击面板中间的Create按钮 - 选择保存位置然后点确定
- 在
Project面板中将动画相关的Sprite拖到Animation面板时间轴上
- 选中挂载了
快捷方式
选中动画相关的Sprite,拖放至的游戏对象上,然后确认Animation Controller和Animation Clip的保存位置。编辑器会自动给游戏对象挂载Animator,并关联Animator Controller
动画控制
过渡
- Has Exit Time:(过渡前动画)是否需要有过渡退出时间
- Conditions:进行过渡的条件
- 若想动画马上过渡(按下按键马上切动画)
- 设置好
Contitions - 反选
Has Exit Time - 将
Transition Duration设为0
- 设置好
使用混合树(Blend Tree)对动画进行混合
目的:按下方向键时,角色播放行走动画,释放时回到待机动画
思路:用2个方向参数决定角色方向,用速度参数决定使用待机动画还是行走动画
步骤:
-
添加3个参数:XVal、YVal、MoveScale
-
按步骤(混合树(Blend Tree)的应用)添加2个混合树,分别是:
-
待机(Idle)混合树
-
行走(Walk)混合树
-
-
添加这两个混合树之间的过渡
- 注意不需要退出时间和过渡时间
⬆️待机到行走(行走到待机同理)
- 注意不需要退出时间和过渡时间
-
修改角色脚本
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);
}
效果
问题:释放按钮后,角色会自动切到向下的Idle动画,原因是XVal和YVal都是0,混合树中没有匹配条件的动画,就自动使用第一个动画了
解决思路:有输入才更新两个方向参数,不然保留之前的
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);
}
效果
又有一个问题:角色的移动速度时快时慢,原因是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);
}
更进一步,跑起来
需求:
- 快速按下2次同样的方向键(第二次按住不放),激活跑步,移动速度加倍
- 跑步状态下可改变方向
- 没方向输入后,跑步状态解除
思路:
- 当动画状态由待机切到行走时(即按下方向键)
- 记录
行走方向 - 记录
开始行走时间 - 若之前已有记录
行走方向且与当前的一样,且当前时间与上次行走结束时间之差在一定范围内,则判定为激活了奔跑状态
- 记录
- 当动画状态从行走切回待机时(即释放方向键)
- 首次按下释放不能太慢,所以想得到有效的首次释放时间,条件是当前时间与
开始行走时间之差在一定范围内,记录此时间为上次行走结束时间
- 首次按下释放不能太慢,所以想得到有效的首次释放时间,条件是当前时间与
- 当动画状态从跑步切回待机时(也是释放方向键)
- 有可能正在转向,中间会有个没有方向输入的过程,不能判定为解除了奔跑状态
- 所以在一定时间后如果状态还是待机的话,则判定为解除了奔跑状态
- 其他
- 支持所有方向按钮的输入,所以不能将按键判断逻辑写死
TileMap
创建图层至涂刷地面
创建TileMap图层
在层级面板中右键创建图层
命名为 Ground
创建新调色板然后新增图块
在 Tile 调色板面板中创建新调色板
命名好点创建
调色板保存路径自行选择(我用 Assets/Art/Tilemap),调色板配置文件就会保存到该目录下
将图片拖到调色板中,以新增图块
释放鼠标后会确认保存位置(还是使用上次的路径吧),确认好命名然后点保存即可。图块新增成功
使用刚新增的图块涂刷 Ground 图层
- 在调色板面板中确认选中的图层是 Ground(暂时只有这个)
- 选中要涂刷的图块
- 点击涂刷工具
鼠标移到场景面板中按需涂刷