2.Unity2D 横版 帧动画sprite animation+动画状态机animator+丝滑连击动作
Posted ζั͡ ั͡雾 ั͡狼 ั͡✾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2.Unity2D 横版 帧动画sprite animation+动画状态机animator+丝滑连击动作相关的知识,希望对你有一定的参考价值。
1.帧动画sprite animation的创建
2.动画状态机animator
教学链接https://blog.csdn.net/linxinfa/article/details/94392971?spm=1001.2014.3001.5506
为角色增加一个animator组件,并创建加一个动画控制器,拖入。
打开动画控制器,将动画拖入到动画控制器里面(只有一个控制器会自动添加)。然后右键动画。创建连接,根据逻辑关系将动画连接起来。然后在左上方点击“参数”。点击连接的线。在右边condition下增加一些动画转变的参数条件。通过脚本来控制参数,动画转变条件。
3. 连击动作(四连)
教学链接https://blog.csdn.net/weixin_30877755/article/details/95343666?spm=1001.2014.3001.5506
图层及其参数 。将每个链接的退出时间改成0,且固定时间改成0
参数条件举例
为什么设置了attack之后还要设置normalizedTime参数?因为如果设置一个参数的话,你点击攻击按钮会直接跳转到下一个动作。并不能完整的将攻击动作放完,那么就多添加一个。他们参数用来判断行为达到哪个阶段,并通过脚本来控制他们参数在进入因为和退出行为时都设置normalizedTime成零。这样就可以使得你点击攻击按钮动作放完了之后才到下一个动作。
角色脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerControl : MonoBehaviour
public bool Iscanjump = false;//是否能跳跃,默认不能
private Rigidbody2D rig;//2D刚体
float ScalX;//获取初始Scale.x,用于转向
public float dropConst;//下坠常数
public float speed;//地面移动速度
public float jumpspeedUp;//上升速度
public float jumpspeedVertiacal;//空中左右移动速度
private Animator ani;//动画控制器
private AnimatorStateInfo state;//动画状态
// Start is called before the first frame update
void Start()
rig = GetComponent<Rigidbody2D>();//获取刚体
ani = GetComponent<Animator>();//获取动画控制器
ScalX = transform.localScale.x;
// Update is called once per frame
void Update()
move();//移动函数
attack();//攻击函数-四连击
private void move()
//水平,垂直俩个轴系
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
float dir = Input.GetAxisRaw("Horizontal");//方向-1 0 1
//跳跃
if (v > 0 && Iscanjump == true)
rig.velocity = new Vector2(0, jumpspeedUp);//设置刚体速度,给予向量
//长按高跳
if (rig.velocity.y > 0 && Input.GetKey(KeyCode.W) && Iscanjump == false)
rig.velocity += Vector2.up * 0.2f;//长按高跳额外得到向上速度
//优化手感
float a = dropConst * 5 - Mathf.Abs(rig.velocity.y);//通过下坠常数,空中速度快为0时,下坠常数a越大,即越快速 度过这个状态
rig.velocity -= Vector2.up * a * Time.deltaTime;
//方向改变
if (dir != 0)
transform.localScale = new Vector3(dir* ScalX, transform.localScale.y, transform.localScale.z);//通过改变scale改变方向
//左右移动
Vector3 vt = new Vector3(h, 0, 0).normalized;//vt为俩个轴系合成的方向向量,normalized单位化
//移动动画
if (dir != 0)
ani.SetBool("Ismove", true);
else ani.SetBool("Ismove", false);
//空中左右移动,为地面jumpspeedVertiacal倍
if (h != 0 && Iscanjump == false)
gameObject.transform.Translate(vt * speed * jumpspeedVertiacal * Time.deltaTime);//通过这个函数来使用vt使得左右移动
//地面左右移动
else gameObject.transform.Translate(vt * speed * Time.deltaTime);
private void attack()
state = ani.GetCurrentAnimatorStateInfo(0);
//判断播放完
if ((state.IsName("attack1") || state.IsName("attack2") || state.IsName("attack3") || state.IsName("attack4")) && state.normalizedTime >= 1.0f)
ani.SetInteger("attack", 0);
if (Input.GetKey(KeyCode.J))
if (state.IsName("idle")|| state.IsName("move") && ani.GetInteger("attack")==0 )
ani.SetInteger("attack", 1);
else if (state.IsName("attack1")|| state.IsName("move") && ani.GetInteger("attack") == 1 )
ani.SetInteger("attack", 2);
else if (state.IsName("attack2")|| state.IsName("move") && ani.GetInteger("attack") == 2)
ani.SetInteger("attack", 3);
else if (state.IsName("attack3")|| state.IsName("move") && ani.GetInteger("attack") == 3)
ani.SetInteger("attack", 4);
if (state.normalizedTime >=1.0f)
ani.SetFloat("normalizedTime", state.normalizedTime);
if (state.normalizedTime>=1&& ani.GetInteger("attack")==0)
ani.SetLayerWeight(ani.GetLayerIndex("attack"), 0);
bottom脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IsJump : MonoBehaviour
//为了优化跳跃碰撞盒,在父物体下面新建空对象bottoom,并添加碰撞盒,用来检测底部(以前碰撞盒头碰到顶部地面还能跳不符合常理,所以需要作此操作)
// Start is called before the first frame update
void Start()
// Update is called once per frame
void Update()
//检测否在地面碰撞盒子检测,通过给地面碰撞盒子transform的tag标签为ground
private void OnCollisionStay2D(Collision2D collision)
if (collision.transform.tag == "ground")
gameObject.GetComponentInParent<playerControl>().Iscanjump = true;//获取父物体脚本变量并赋值
private void OnCollisionExit2D(Collision2D collision)
if (collision.transform.tag == "ground")
gameObject.GetComponentInParent<playerControl>().Iscanjump = false;//获取父物体脚本变量并赋值
状态机里的动画行为脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SetNormalizedTime : StateMachineBehaviour
private string normalizedTime = "normalizedTime";
// OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
animator.SetFloat(normalizedTime, 0);
// OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks
override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
animator.SetFloat(normalizedTime, stateInfo.normalizedTime);
// OnStateExit is called when a transition ends and the state machine finishes evaluating this state
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
animator.SetFloat(normalizedTime, 0);
下一篇
03 canvas帧动画封装案例
sprite.js
/** * Created by suxiaoxia on 2017/7/15. */ function sprite(option) { this._init(option); } sprite.prototype = { /*初始化*/ _init:function (option) { this.x = option.x || 0; this.y = option.y || 0; this.w = option.w || 40; this.h = option.h || 65; this.fps = option.fps || 10; this.originW = option.originW || 40; this.originH = option.originH || 65; this._dirIndex = 0; this._imgSrc = option.imgSrc || ‘‘; }, render:function (ctx) { var img = new Image(); img.src = this._imgSrc; var self = this; img.onload = function () { var frameIndex = 0; setInterval(function () { ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height); ctx.drawImage( img, frameIndex*self.originW, self._dirIndex*self.originH, self.originW, self.originH, self.x, self.y, self.w, self.h ); frameIndex++; frameIndex %= 4; },1000/self.fps) } }, changeDir:function (dir) { if (dir == ‘left‘){ this._dirIndex = 1; } if (dir == ‘right‘){ this._dirIndex = 2; } if (dir == ‘up‘){ this._dirIndex = 3; } if (dir == ‘down‘){ this._dirIndex = 0; } } };
index.html
<head> <meta charset="UTF-8"> <title>Title</title> //引入sprite.js文件 <script src="sprite.js"></script> </head> <body> <div> <canvas id="canvas"> 你的浏览器不支持canvas,请升级浏览器 </canvas> </div> <button id="btn-dir-left">←</button> <button id="btn-dir-right">→</button> <button id="btn-dir-up">↑</button> <button id="btn-dir-down">↓</button> <script> (function () { var canvas = document.querySelector("#canvas"); var ctx = canvas.getContext(‘2d‘); canvas.width = 600; canvas.height = 600; canvas.style.border = "1px solid #000"; var s = new sprite({ x:300, y:300, w:80, h:65*2, fps:4, originW:40, originH:65, imgSrc:‘../img_a/DMMban.png‘ }); s.render(ctx); //绑定按钮的点击事件 var btnLeft = document.getElementById(‘btn-dir-left‘); btnLeft.onclick = function() { s.changeDir(‘left‘); }; var btnRight = document.getElementById(‘btn-dir-right‘); btnRight.onclick = function() { s.changeDir(‘right‘); }; var btnUp = document.getElementById("btn-dir-up"); btnUp.onclick = function() { s.changeDir(‘up‘); }; var btnDown = document.getElementById(‘btn-dir-down‘); btnDown.onclick = function() { s.changeDir(‘down‘); }; })(); </script> </body>
以上是关于2.Unity2D 横版 帧动画sprite animation+动画状态机animator+丝滑连击动作的主要内容,如果未能解决你的问题,请参考以下文章