37.2D动画-2D序列帧动画
37.1 知识点
什么是序列帧动画
- 我们最常见的序列帧动画就是我们看的日本动画片,以固定时间间隔按序列切换图片就是序列帧动画的本质。当固定时间间隔足够短时,我们肉眼就会认为图片是连续动态的,进而形成动画(会动的画面)。
- 它的本质和游戏的帧率概念有点类似。
- 原理就是在一个循环中按一定时间间隔不停地切换显示的图片。
代码制作序列帧动画
在场景中创建一个2D精灵对象
在场景中创建一个2D精灵对象。创建脚本挂载上去,脚本声明一个Sprite数组,用于存放序列帧图片,在Inspector窗口关联。
public Sprite[] sprs; //声明一个Sprite数组,用于存放序列帧图片
代码中添加计时器做法
代码中添加计时器做法,每隔一段时间切换精灵图片,模拟动画效果。
public class Lesson37_2D动画_2D序列帧动画 : MonoBehaviour
{
public Sprite[] sprs; //声明一个Sprite数组,用于存放序列帧图片
private SpriteRenderer sr; //声明一个SpriteRenderer组件,用于显示图片
private float time = 0; //声明一个float变量,用于记录帧间隔时间
private int nowIndex = 0; //声明一个int变量,用于记录当前显示的图片索引
void Start()
{
sr = this.GetComponent<SpriteRenderer>(); //获取当前物体上的SpriteRenderer组件
sr.sprite = sprs[nowIndex]; //将SpriteRenderer组件的sprite属性设置为数组中第一个元素
}
void Update()
{
//每一次增加帧间隔时间
time += Time.deltaTime;
//当帧间隔时间达到某一个条件时就切换图片
if (time >= 0.03f)
{
//索引增加 切换图片
nowIndex++;
//如果显示到最后一张了 从头显示
if (nowIndex >= sprs.Length)
nowIndex = 0;
sr.sprite = sprs[nowIndex];
time = 0;
}
}
}
Animation窗口制作序列帧动画
方法一
- 创建一个空物体
- 创建一个动画
- 直接将某一个动作的序列帧拖入窗口中
- 注意:需要的话可以修改动画帧率来控制动画的播放速度。可以在Animation窗口修改,也可以打开Debug模式修改。一般来说是先删除完原动画修改帧率后再重新把一个动作的序列帧动画重新拖入,直接修改可能会有帧丢失。
方法二
- 直接将图片拖入Hierarchy层级窗口中
- 拖入后会直接创建对象,并且动画已经创建好了
利用Animator进行动画控制
创建好动画,设置好切换参数和条件等
代码中拖拽得到动画控制器
代码中拖拽得到动画控制器,根据按下空格逻辑切换动画。
public class Lesson37_2D动画_2D序列帧动画 : MonoBehaviour
{
public Animator animator; //声明一个Animator组件,用于控制动画状态机
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
animator.SetBool("isDown", true); //当按下空格键时,设置Animator组件中isDown布尔值为true,触发过渡到下落状态
else if (Input.GetKeyUp(KeyCode.Space))
animator.SetBool("isDown", false); //当松开空格键时,设置Animator组件中isDown布尔值为false,触发过渡到原始状态
}
}
37.2 知识点代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson37_2D动画_2D序列帧动画 : MonoBehaviour
{
#region 知识点二 代码制作序列帧动画
public Sprite[] sprs; //声明一个Sprite数组,用于存放序列帧图片
private SpriteRenderer sr; //声明一个SpriteRenderer组件,用于显示图片
private float time = 0; //声明一个float变量,用于记录帧间隔时间
private int nowIndex = 0; //声明一个int变量,用于记录当前显示的图片索引
#endregion
#region 知识点四 利用Animator进行动画控制
public Animator animator; //声明一个Animator组件,用于控制动画状态机
#endregion
void Start()
{
#region 知识点一 什么是序列帧动画
//我们最常见的序列帧动画就是我们看的 日本动画片
//以固定时间间隔 按序列切换图片 就是 序列帧动画的本质
//当固定时间间隔足够短时 我们肉眼就会认为图片是连续动态的 进而形成动画(会动的画面)
//它的本质和游戏的帧率概念有点类似
//原理就是在一个循环中按一定时间间隔不停的切换显示的图片
#endregion
#region 知识点二 代码制作序列帧动画
//我们先尝试用原理 通过代码来实现序列帧动画
sr = this.GetComponent<SpriteRenderer>(); //获取当前物体上的SpriteRenderer组件
sr.sprite = sprs[nowIndex]; //将SpriteRenderer组件的sprite属性设置为数组中第一个元素
#endregion
#region 知识点三 Animation窗口制作序列帧动画
//方法一:
//1.创建一个空物体
//2.创建一个动画
//3.直接将某一个动作的序列帧拖入窗口中
//方法二:
//直接将图片拖入Hierarchy层级窗口中
//注意:需要的话可以修改动画帧率 来控制动画的播放速度
#endregion
#region 知识点四 利用Animator进行动画控制
#endregion
}
void Update()
{
#region 知识点二 代码制作序列帧动画
//每一次增加帧间隔时间
time += Time.deltaTime;
//当帧间隔时间达到某一个条件时 就切换图片
if (time >= 0.03f)
{
//索引增加 切换图片
nowIndex++;
//如果显示到最后一张了 从头显示
if (nowIndex >= sprs.Length)
nowIndex = 0;
sr.sprite = sprs[nowIndex];
time = 0;
}
#endregion
#region 知识点四 利用Animator进行动画控制
if (Input.GetKeyDown(KeyCode.Space))
animator.SetBool("isDown", true); //当按下空格键时,设置Animator组件中isDown布尔值为true,触发过渡到下落状态
else if (Input.GetKeyUp(KeyCode.Space))
animator.SetBool("isDown", false); //当松开空格键时,设置Animator组件中isDown布尔值为false,触发过渡到原始状态
#endregion
}
}
37.3 练习题
在之前2D相关练习题的基础上,为控制的对象加上序列帧动画
给机器人创建待机动画,找到待机动画图集,拖入图片进去。注意图集要设置底部为轴心
给机器人创建走路动画,找到待机走路图集,拖入图片进去。注意图集要设置底部为轴心
给机器人创建跳跃动画,找到跳跃动画图集,拖入图片进去。注意图集要设置底部为轴心
创建x,y速度的int动画参数,并且添加过渡和切换条件。x速度等不等于0决定是Idle状态还是Walk状态,y速度等不等于0决定是跳跃状态还是非跳跃状态。
在玩家控制脚本的代码中添加设置x,y速度的int动画参数的逻辑。x速度根据输入判断,y速度根据刚体判断
h = Input.GetAxisRaw("Horizontal");
animator.SetInteger("xSpeed", (int)h);
animator.SetInteger("ySpeed", Mathf.CeilToInt(rigidBody2D.velocity.y));
注意跳跃动作改成只播放一次
还存在跳跃动作多次播放的原因是因为在上升下落的时候某一瞬间y速度会为0,这个时候会切换动画。优化的话可以在玩家底部添加子对象,添加触发碰撞器,判断是否接触地面,来设置一个布尔参数判断是不是在跳跃
37.4 练习题代码
// 引用命名空间
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 声明一个类
public class Lesson37_练习题_PlayerObject : MonoBehaviour
{
// 声明一个浮点数类型变量 moveSpeed; 访问属性为 public,其他脚本可以访问
public float moveSpeed = 5;
// 声明一个浮点数类型变量 h;
private float h;
// 声明 SpriteRenderer 类型变量 sr;
private SpriteRenderer sr;
// 声明 Rigidbody2D 类型变量 rigidBody2D;
private Rigidbody2D rigidBody2D;
// 声明一个浮点数类型变量 frontH;
private float frontH;
// 声明 Animator 类型变量 animator;
private Animator animator;
// Start 方法在场景加载后第一时间执行
void Start()
{
// 获取组件 SpriteRenderer 的引用赋值给 sr;
sr = this.GetComponent<SpriteRenderer>();
// 获取组件 Rigidbody2D 的引用赋值给 rigidBody2D;
rigidBody2D = this.GetComponent<Rigidbody2D>();
// 获取组件 Animator 的引用赋值给 animator;
animator = this.GetComponent<Animator>();
}
// Update 方法在每一帧更新时执行
void Update()
{
// 获取输入设备水平轴的值并赋值给 h;
h = Input.GetAxisRaw("Horizontal");
// 设置动画参数 xSpeed 为 h 的整数值
animator.SetInteger("xSpeed", (int)h);
// 设置动画参数 ySpeed 为刚体 y 方向速度的整数值
animator.SetInteger("ySpeed", Mathf.CeilToInt(rigidBody2D.velocity.y));
// 根据输入,改变刚体速度
if (h != 0)
rigidBody2D.velocity = new Vector2(h * moveSpeed, rigidBody2D.velocity.y);
// 根据水平轴值 h 改变 SpriteRenderer 的 flipX 属性
if (h < 0)
sr.flipX = true;
else if (h > 0)
sr.flipX = false;
// 当按下空格键时,创建子弹并告诉它朝哪里发射
if (Input.GetKeyDown(KeyCode.Space))
{
GameObject obj = Instantiate(Resources.Load<GameObject>("BulletObj"), this.transform.position + new Vector3(sr.flipX ? -0.3f : 0.3f, 0.5f, 0), Quaternion.identity);
obj.GetComponent<BulletObj>().ChangeMoveDir(sr.flipX ? Vector3.left : Vector3.right);
}
// 当按下 J 键时,给刚体施加一个向上的瞬时力
if (Input.GetKeyDown(KeyCode.J))
{
rigidBody2D.AddForce(Vector2.up * 300);
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com