之前写过一个系列《HTML5 2D平台游戏开发》,在此过程中发现有很多知识点没有掌握,而且用纯JavaScript来开发一个游戏效率极低,因为调试与地图编辑都没有可视化的工具,开发起来费时费力,加上业余时间有限,我决定暂且中止开发。为了弥补缺少的知识点,我打算先学习和借鉴一下Unity的开发思路,于是把原先的游戏素材移植了过来。首先还是先从人物的动作开始,Unity的动画与之前开发时的思路有很大不同,Unity没有“帧”这一概念,也就是说没有办法获取到当前动画播放到第几帧,只能通过normalizedTime来获取动画播放的百分比进度,一下子让适应这种模式有些困难。先不考虑代码实现细节,整理一下思路,人物实现三连击的状态机大致如下:

  1. Idle ⇢ attack_a ⇢ Idle
  2. Idle ⇢ attack_a ⇢ attack_b ⇢ Idle
  3. Idle ⇢ attack_a ⇢ attack_b ⇢ attack_c ⇢ Idle

在Idle状态下按下攻击键,过渡到attack_a,如果没有下一步操作,attack_a动画播放完毕后还原到Idle状态。如果在attack_a状态下再次按下攻击键,则过渡到attack_b,如果在attack_b状态下无操作,动画播放完毕后还原到Idle,依此类推,多段连击也是一样的。为了表示攻击的状态,需要为Animator添加一个attack参数:

attack等于0表示处于非攻击状态,attack等于1表示处于attack_a,2和3分别表示处于attack_b、attack_c。

接下来一步一步分析各个状态间的过渡。

Idle ⇢ attack_a

  Idle状态可以随时通过按下攻击键打断并过渡到attack_a,故没有 Has Exit Time ,其它项也都置为0。

attack_a ⇢ Idle

  最初我是这样考虑的,给这个过渡设置 Has Exit Time ,如果没有任何操作,让其还原到Idle,于是有了

 

但最终运行时攻击总是会卡在最后一帧一段时间,只有把Exit Time设置为0.1才流畅。也许是动画播放速度设置太快的缘故,但我总觉得通过Exit Time的方式来实现不太好。在查阅一番资料后,我觉得给动作添加Behaviour是比较好的方式。选中attack_a,为其添加一个名为SetNormalizeTime的Behaviour:

public class SetNormalizedTime : StateMachineBehaviour {
private string targetParameter = "Normalized Time"; // 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(targetParameter, );
} // OnStateUpdate is called on each Update frame between OnStateEnter and OnStateExit callbacks
override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
animator.SetFloat(targetParameter, 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(targetParameter, );
}
}

每次进入该状态,先将Normalized Time重置为0,表示动画从头开始,然后在OnStateUpdate中更新它,最后退出时再置为0。同时也别忘了在Animator中添加一个名为Normalized Time的参数(float类型):

现在可以把attack_a ⇢ Idle的 Has Exit Time 去掉了,同时添加一个 Conditions

表示当动画播放完毕时(NormalizeTime > 1.0f) 过渡到 Idle。同样的,也给attack_b ⇢ Idle 和 attack_c ⇢ Idle 附加上这个 Behaviour。

代码实现

  常规操作:

private Animator anim;
private Rigidbody2D myRigidbody;
private AnimatorStateInfo stateInfo; public int hitCount = ; //0:表示idle状态。 1:表示当前正在进行attack_a。 2:attack_b。 3:attack_c。 void Start ()
{
anim = GetComponent<Animator>(); //获取动画组件
myRigidbody = GetComponent<Rigidbody2D>(); //获取刚体组件
} void Update()
{
stateInfo = anim.GetCurrentAnimatorStateInfo();
HandleInput();
}

下面实现HandleInput方法:

void HandleInput()
{
//若动画为三种状态之一并且已经播放完毕
if ((stateInfo.IsName("attack_a") || stateInfo.IsName("attack_b") || stateInfo.IsName("attack_c")) && stateInfo.normalizedTime > 1.0f)
{
hitCount = ; //将hitCount重置为0,即Idle状态
anim.SetInteger("attack", hitCount);
attack = false;
} //按下键盘J键攻击
if (Input.GetKeyDown(KeyCode.J))
{
HandleAttack();
} }

(这里踩了一个坑,实现这部分逻辑时我是远程操作完成的,发送的指令实际上有一定的延迟,这样就导致按住键盘J键不放可以连续触发攻击,也就是连发。让我误以为GetKeyDown是连续触发的,实际上GetKeyDown只触发一次。)

HandleAttack的实现:

void HandleAttack()
{
//若处于Idle状态,则直接打断并过渡到attack_a(攻击阶段一)
if (stateInfo.IsName("Idle") && hitCount == )
{
hitCount = ;
anim.SetInteger("attack", hitCount);
}
//如果当前动画处于attack_a(攻击阶段一)并且该动画播放进度小于80%,此时按下攻击键可过渡到攻击阶段二
else if(stateInfo.IsName("attack_a") && hitCount == && stateInfo.normalizedTime < 0.8f)
{
hitCount = ;
}
//同上
else if(stateInfo.IsName("attack_b") && hitCount == && stateInfo.normalizedTime < 0.8f)
{
hitCount = ;
}
}

这里要注意,比如在触发第二段攻击时需要满足条件 normalizedTime < 0.8f ,但此时按下攻击键是不会马上播放第二段攻击动画的,如果马上播放就显得动作非常不协调了,应该等到第一阶段的攻击动画播放到一定阶段才播放第二段攻击动画。所以需要给关键帧添加一个方法,告诉动画系统在这一帧要执行某个指令。

void GoToNextAttackAction()
{
anim.SetInteger("attack", hitCount);
}

给第7帧添加一个事件,指向 GoToNextAttackAction 这个方法,动画将在第7帧的时候被打断并进入下一个攻击动画。如果hitCount没有改变,SetInteger("attack",hitCount) 不会影响当前正在播放的动画,动画会持续播放完毕(至第9帧)。

P.S. 虽然费了一些周折,但还是把效果实现出来了,Unity的开发效率比JS高出太多,大概100倍左右吧,这是在开发过程中的感觉。不知道离游戏成品还有多遥远,但我还是会继续学习。

Unity2D实现人物三连击的更多相关文章

  1. Unity - HasExitTime用法

    本文详细分析了AnimatorController中动画切换过渡问题,即Translation过渡及hasExitTime的问题.方法为对实际项目中的所有情况进行分类,规划逻辑图,可视化分析解决这些问 ...

  2. [开发ing] Unity项目 - Hero英雄

    目录 游戏原型 项目演示 绘图资源 代码实现 技术探讨 参考来源 游戏原型 游戏介绍:这是一款横版类魂游戏,玩家将操控Hero,在诸神黄昏的墓地中,挑战源源不断的敌人,以及近乎无敌的强大boss 灵感 ...

  3. 时光煮雨 Unity3D实现2D人物动画② Unity2D 动画系统&资源效率

    系列目录 [Unity3D基础]让物体动起来①--基于UGUI的鼠标点击移动 [Unity3D基础]让物体动起来②--UGUI鼠标点击逐帧移动 时光煮雨 Unity3D让物体动起来③—UGUI DoT ...

  4. Unity2D 人物移动切换人物图片

      勾选Constraints_freeze Rotation_z轴锁定,防止碰撞偏移.        public float moveSpeed = 3f;//定义移动速度        priv ...

  5. 时光煮雨 Unity3D实现2D人物移动-总结篇

    系列目录 [Unity3D基础]让物体动起来①--基于UGUI的鼠标点击移动 [Unity3D基础]让物体动起来②--UGUI鼠标点击逐帧移动 时光煮雨 Unity3D让物体动起来③—UGUI DoT ...

  6. 时光煮雨 Unity3D实现2D人物动画① UGUI&Native2D序列帧动画

    系列目录 [Unity3D基础]让物体动起来①--基于UGUI的鼠标点击移动 [Unity3D基础]让物体动起来②--UGUI鼠标点击逐帧移动 时光煮雨 Unity3D让物体动起来③—UGUI DoT ...

  7. 角色移动优化【Unity2D自学之路】

    自学unity2D独立游戏开发,第一篇自学笔记.在场景中添加角色,并给角色添加Rigidbody2D刚体组件.collection2D碰撞体组件,c#脚本组件控制人物移动和跳跃.c#脚本组件内容如下, ...

  8. 计算机人物系列-Mauchly,Eckert,Goldstine

    关键词:莫尔学院(Moore School),阿伯丁试验场(Aberdeen Proving Ground), 雷明顿兰德公司(Remington Rand Corporation), IBM院士(I ...

  9. Python学习笔记(2) Python提取《釜山行》人物关系

    参考:http://www.jianshu.com/p/3bd06f8816d7 项目原理:   实验基于简单共现关系,编写 Python 代码从纯文本中提取出人物关系网络,并用Gephi 将生成的网 ...

随机推荐

  1. 2018 CCPC 女生专场

    可能是史上最弱的验题人—— Problem A (小)模拟. #include <bits/stdc++.h> using namespace std; int T; int main() ...

  2. 51Nod - 1405 树的距离之和(树形DP)

    1405 树的距离之和 题意 给定一棵无根树,假设它有n个节点,节点编号从1到n,求任意两点之间的距离(最短路径)之和. 分析 树形DP. 首先我们让 \(1\) 为根.要开两个数组 \(up \ d ...

  3. spring属性注入

    1,set方法注入 (1)对于值类型的属性: 在对象中一定要有set方法 package com.songyan.demo1; import com.songyan.injection.Car; /* ...

  4. gedit插件配置

    Ubuntu用户 sudo apt-get install gedit-plugins Fedora用户 yum install gedit-plugins 使用gEdit搭配terminal来写程序 ...

  5. Linux文件名小写的好处(转)

    说明:来自老阮的<为什么文件名要小写>的文章,其实我觉得应该说是<Linux文件名为什么要小写>会更合适些. 一.可移植性 Linux 系统是大小写敏感的,而 Windows ...

  6. android intent 跳转

    转自:http://blog.sina.com.cn/s/blog_7309444701014u2d.html 一.不需要返回值的跳转 Intent intent=new Intent(); inte ...

  7. 直方图均衡(HE)与局部色调映射(LTM) .

    直方图均衡(Histogram Equalization)是图像处理中一个十分基础的概念,具有调整图像灰度,增强对比度的作用.    限制对比度自适应直方图均衡(Contrast Limited Ad ...

  8. python学习心得

    一,高级特性: 1,切片:[start:stop:step] >>>l=range() >>>l[,-,] resulte is [] 2,迭代 2.1按iterv ...

  9. ECSHOP搜索框文字点击消失

    <input name="keywords" type="text" id="keyword" value="黄山金银币&q ...

  10. 2017.4.26 慕课网--Java 高并发秒杀API配置文件(持续更新)

    新建项目,new maven project. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&q ...