之前写过一个系列《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. SenseTime Ace Coder Challenge 暨 商汤在线编程挑战赛*

    题目链接   Problems Problem A Problem B bitset…… Problem C Problem D Problem E Problem F Problem G 考虑最小生 ...

  2. Python的并发并行[1] -> 线程[2] -> 锁与信号量

    锁与信号量 目录 添加线程锁 锁的本质 互斥锁与可重入锁 死锁的产生 锁的上下文管理 信号量与有界信号量 1 添加线程锁 由于多线程对资源的抢占顺序不同,可能会产生冲突,通过添加线程锁来对共有资源进行 ...

  3. 「kuangbin带你飞」专题十八 后缀数组

    layout: post title: 「kuangbin带你飞」专题十八 后缀数组 author: "luowentaoaa" catalog: true tags: - kua ...

  4. jQuery笔记:checkbox

    用jQuery操作checkbox时的一点小问题. 勾选checkbox的时候,$("#id").attr("checked")变为"checked& ...

  5. java copy array

    13down voteaccepted Here's a java 1.4 compatible 1.5-liner: int[] array = { 1, 2, 3, 4, 5 }; int siz ...

  6. (转) view视图的放大、缩小、旋转

    控件移动,放大,缩小,旋转 1,代码添加控件 例如: /* 1.创建一个控件 2.设置控件的位置,大小 3.设置控件所需要的各个属性 4.添加入父控件 5.添加监听 */ UIButton *btn1 ...

  7. 设计模式之不变模式(Immutable Pattern)分析

    http://www.iteye.com/topic/959751 最近老有人问我不变模式,我其实也理解得不深,于是花了一些时间进行学习总结,分析了一下不变模式(immutable pattern), ...

  8. [洛谷3796]【模板】AC自动机(加强版)

    题目大意: 给定$n(n\leq150)$个模式串$p_i(|p_i|\le70)$和一个$t(|t|\le10^6)$,求$t$中被匹配次数最多的$p_i$. 思路: AC自动机.匹配时记录一下匹配 ...

  9. [Luogu1429]平面最近点对(加强版)

    题目大意: 平面最近点对. 思路: 分治. 首先将所有点排序 每次把当前区间分为两半,递归求解两个区间内部的情况,然后枚举区间两边的点. #include<cmath> #include& ...

  10. Bean装配--xml

    1,bean package com.songyan.zhangpei; import java.util.ArrayList; import com.sun.xml.internal.bind.v2 ...