unity游戏开发毕设_毕设分享:⽤Unity探究2D游戏的打击感这是我毕业设计的⼀部分 emmm……我的毕设和格⽃游戏相关,⽽对于打击感的研究算是其中我⽐较在意的⼀环。现在临近毕业,我将毕设中开发部分的⼀些内容整理出来分享,希望能通过这样学习到更多的东西。
打击感为何物?
字⾯意思,“打到了的感觉”;好的打击感是易读的,包含信息充⾜的;它可以让玩家感受到这次的攻击奏效了、这次攻击的轻重程度、感受到这是怎样的攻击。在电⼦游戏中,则通过视觉和听觉呈现这些。
实现⽅式
市⾯上已经有很多作品供我们参考,让我⾃⼰想出⼀个独特的实现⽅式如同天⽅夜谭,不过我喜欢参照已有作品,去探究他们如何实现。
1)帧冻结(顿帧)
顿帧已经是司空见惯的⼿段,也是⽬前最常见的表现打击感的⽅式。它会让⾓⾊动画停⽌在那⾥,让玩家意识到发⽣了什么,接着再继续播放动画。我认为所有的打击感⼏乎都有这个东西,只不过可能有些帧冻结的时间设置,让⼈很难⽤⾁眼察觉到。在《街霸 4》中,击中时普遍的顿帧时间为:攻击⾓⾊顿 14/60 帧≈ 0.23 秒,受击⾓⾊顿 16/60 帧≈ 0.26 秒,是我见过最长的。
⼀般情况下,顿帧的时间不会超过 0.3 秒,除⾮是做特殊的效果处理,因为超过 0.3 秒这个图像在玩家眼⾥会变得⾮常突出,显得较为奇怪。通常程度越重的攻击顿帧的时间也越长,⽽这也需要适当的动作设计,⽐如较长时间的出⼿准备动作能让玩家对这次攻击有⼀个“很重”的预期。
2)击退距离
除⾮有特殊需求,不然⼤多数游戏在攻击后,双⽅⾓⾊之间的距离⼀定会产⽣变化。这是⾮常容易表现⼀个攻击轻重程度的⽅式。
顿帧+击退 是我认为最主要的两个⽅式,运⽤这两者,即可实现最基本的打击感。那么在这基础上,可以添加⼀些“特效”来使它更加充实。
3)特效
可以有很多种,我认为这些就像是在打击感上加花,使它更加丰满。我通过总结,列举了⼀些常见⼿段:打击⽕花(HitFire):攻击奏效时在特定位置创建。需要注意画风适当,风格对应;斩击有斩击的样式,拳击有拳击的样式,重攻击应该⽐轻攻击的⽕花更⼤更饱和等等。
精灵(Sprite)抖动:我们在很多游戏⾥可能都会看到,当⾓⾊受到攻击时,帧冻结期间⾓⾊的图⽚(Sprite)也在颤动,颤动的⽅式有多种,⽔平及垂直⽅向的,或是虚影向外扩张的(我不知道那种形式该
怎么表述)。但这仅限于视觉上的抖动,该抖动不会有任何逻辑上的影响,⽐如⾓⾊的物理坐标,判定框这些均不会随着精灵的抖动⽽改变。
屏幕震动:很多游戏都会通过震屏来彰显⼀次攻击的冲击⼒,震屏的⽅式以及怎样去表现不同的攻击,这值得研究。
颜⾊变化:有些动作游戏会让⾓⾊在受击的时候,⾝体颜⾊产⽣变化,⼤多是在那⼀瞬间,⾝体闪⼀下相应颜⾊,红⾊和⽩⾊较为常见。这会让玩家更容易读出⾓⾊正在挨打这件事。
本次毕设我主要采取了 帧冻结 + 击退 + 精灵抖动 + 打击⽕花 的组合进⾏实现。
下⾯是在 Unity 中的应⽤:
1. HitBox 与 HurtBox 的搭建
单人开发选ue4还是unity先简单说下我对游戏中攻击和受击的实现吧。
我的⾓⾊总共有 3 种攻击⽅式,⽽我为每⼀种攻击⽅式在⾓⾊下⾯都创建了⼀个⼦物体;
每⼀个攻击⼦物体,都有他们对应的 BoxCollider2D(IsTriiger) 来代表他们的攻击判定,同理,HurtBox 也⼀样。
我⽤ Animator 的帧事件控制每个攻击动作开启攻击判定的时机和位置。private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.tag == "Hurt2")
{
}
}
我会在 OnTriggerEnter2D 函数⾥⾯实现攻击需要发⽣的事情,若攻击物体碰到了标签为“Hurt2”(2P 的受击判定框)的物体时,攻击便发⽣了。
2. 逻辑流程
在讨论实现之前,我想先梳理⼀下逻辑流程,先是攻击⾓⾊的流程:⾸先,在 Hitbox 与 HurtBox 重叠时,我们会判定为攻击奏效,此时我会优先处理的是关闭 HitBox,因为我不希望攻击事件重复发⽣,避免⼀些⿇烦;
之后是“顿帧”,我通过控制动画播放速度,使速度为 0 来实现这⼀功能;
接着我们需要记录下⾓⾊当前的速度(X 轴和 Y 轴),因为接下来我们要锁定⾓⾊的位移了,在帧冻结期间,我们不希望⾓⾊的位置仍在变化;
创建⽕花特效,创建的位置我希望是在判定框相交区间的中⼼位置;
顿帧结束,恢复动画播放;
恢复⾓⾊之前被记录的速度,若本次攻击是空中攻击,那么这之后⾓⾊会继续下落了;
对⾓⾊施加对应⽅向的⼒,以达到击退的效果,也可以是垂直⽅向的⼒,达到浮空或强 DOWN 之类的效果。
那么总结下来,流程就是:
关闭 HitBox→停⽌动画播放→记录当前速度→锁定⾓⾊的 X 轴 Y 轴→创建⽕花→恢复动画播放→恢复⾓⾊速度→施加⼒(击退)
对于受击⾓⾊来说也是类似,不过会多出⼀个抖动的效果,并且不⽤记录⾓⾊速度:
进⼊受击动画→停⽌动画播放(此时应处于受击动画的第⼀帧)→处理精灵抖动(抖动时间应⼩于顿帧时间)→恢复动画播放→施加⼒
好的,整理完了流程,可能在讲实现⽅式的时候思路会更清晰⼀些。
3. 帧冻结的实现
我通过控制 Animator 的播放速度 和 Invoke 函数 这两者结合来实现帧冻结这⼀功能。public float HitStop_AS = 1;
public float HitStop_AO = 1;
public float HitStop_DS = 1;
public float HitStop_DO = 1;
void Start () {
HitStop_AS = HitStop_AS / 60;
HitStop_AO = HitStop_AO / 60;
HitStop_DS = HitStop_DS / 60;
HitStop_DO = HitStop_DO / 60;
}
private void OnTriggerEnter2D(Collider2D collision){
if(collision.tag == "Hurt2")
{
gameObject.GetComponent().speed = 0;
Invoke("AnimPlay", HitStop_AS);
}
}
void AnimPlay() {
gameObject.GetComponent().speed = 1;
}
Invoke 可以让规定的函数在规定时间后启动,⽽我在 Invoke 函数中使⽤的 HitStop_AS 参数就是攻击击中后攻击⾓⾊⾃⾝的帧冻结时间,这⾥的参数需要以秒为单位。
在定义变量时,HitStop 这⼀类参数是以帧为单位定义的,在 public 之后我可以在 Unity 界⾯中很⽅便的以帧的概念进⾏调节,在游戏开始时,便会通过 Start() ⾥⾯的指令转化为秒单位。
我创建了名为 HitStop 的脚本,这些都是写在那个脚本⾥的,⽽我会给每个攻击⼦物体都套上这个脚本,这样每⼀个攻击招式都具备这些模板⼀样的变量了。对此我进⾏了⼀系列的总结。
表 1 攻击招式应具备的模板属性属性备注动画总帧/anim完整攻击动画的帧数;不可调整
发⽣/A概念变量,攻击判定产⽣前的帧数;可调整
攻击持续/KA概念变量,攻击判定持续存在的帧数;可调整
击中时的顿帧/HitStop_AS击中时⾃⾝动画停⽌播放的帧数;可调整
被击中者的顿帧/HitStop_AO被击中者动画停⽌播放的帧数;可调整
被防时的顿帧/HitStop_DS被防御时⾃⾝动画停⽌播放的帧数;可调整
防御者的顿帧/HitStop_DO防御者动画停⽌播放的帧数;可调整
表 2 受击⽅相关属性属性备注受击动画总帧/anim_o完整受击动画的总帧数;不可调整
防御动画帧/anim_d完整防御动画的总帧数;⼤多情况下防御动画都是⼀张同样的图持续多帧;不可调整
表 3 其他相关属性属性备注黄⾦受击帧/zhexue受击顿帧结束后,受击动画⾄少要播放的帧数。即这个帧数会让玩家明确的感受到第⼆次攻击⽣效了;想达到这个效果,夸张的受击动画设计是必要的,动作幅度越⼤,感受就越直观;⽬前还没有⼀个明确的答案能解释多少帧合适,但动作改变幅度明显即可。
连招间歇帧/ComboBreak攻击者的第⼀招命中后,输⼊可以形成连招的第⼆招之前 允许玩家间隔的最⼤帧
这⾥有很多是我⾃⼰总结的⼀些概念,像是⼀些公式也只是出于玩家视⾓理解的知识进⾏总结;格⽃
游戏现在已经发展成了“电⼦竞技”,对于玩家来说,“有利帧”“不利帧”这些都已成为了必修功课,所以我认为这些也有必要列⼊到设计⼯作当中,⽽这些公式或许能帮助我在开发中提供更多的便利,仅供参考。
4. 打击⽕花的创建
先前我使⽤了从不同游戏中的拿过来的美术素材进⾏实验,画风的不统⼀会让⼈觉得很不舒服,因为这是最直观的感受,所以我后来挑了⼀整套同⼀个游戏的素材,效果好多了。
我认为,合适的⽕花特效⾮常重要。同时,特效创建的位置也应合理,我希望⽕花创建在 HitBox 与 HurtBox 相交区间的中⼼处。
为此,我⾃定义了⼀个⼆维向量,⽤来计算相交区间的中⼼坐标:Vector2 hit(BoxCollider2D self, BoxCollider2D oppo)
{
Vector2 hit = new Vector2(1,1);
//===============判定框的中⼼坐标=====================================
float self_pos_x = transform.position.x + self.offset.x;
float self_pos_y = transform.position.y + self.offset.y;
float oppo_pos_x = ansform.position.x + oppo.offset.x;
float oppo_pos_y = ansform.position.y + oppo.offset.y;
if (self_pos_y + self.size.y/2 >= oppo_pos_y + oppo.size.y / 2)
{
if(self_pos_y - self.size.y/2 <= oppo_pos_y - oppo.size.y / 2)
{
hit = ansform.GetChild(0).ansform.position;
}
else
{
hit = new ansform.GetChild(0).ansform.position.x, (self_pos_y - self.size.y / 2) +
((oppo_pos_y + oppo.size.y / 2) - (self_pos_y - self.size.y / 2)) / 2);
}
}
else if (self_pos_y + self.size.y / 2 < oppo_pos_y + oppo.size.y / 2)
{
if(self_pos_y - self.size.y / 2 >= oppo_pos_y - oppo.size.y / 2)
{
hit = new ansform.GetChild(0).ansform.position.x, self_pos_y);
}
else if (self_pos_y - self.size.y / 2 < oppo_pos_y - oppo.size.y / 2)
{
hit = new ansform.GetChild(0).ansform.position.x, (self_pos_y + self.size.y / 2) -
((self_pos_y + self.size.y / 2) - (oppo_pos_y - oppo.size.y / 2)) / 2);
}
}
return hit;
}
之后通过 Instantiate() 函数在 OnTriggerEnter2D() 中实现创建的功能。
5. 精灵抖动
⾓⾊ sprite 的抖动仅限于视觉上,⾓⾊的物理坐标不会随着抖动⽽变化。为了实现这⼀逻辑,我在 sprite 物体上创建了⼀个⽗物体,⽽⾓⾊的物理 BoxCollider 以及 RigidBody 等组件都会套在这个⽗物体上。
⽗物体的运动会影响到⼦物体,但⼦物体的运动不会影响⽗物体,这样在 Sprite 抖动的时候就不会影响到物理判定框了。public float A = 1;
public float speed = 1;
float x = 0;
bool swag = false;
if (swag){
x = x + speed * Time.deltaTime;
transform.position.y, transform.position.z);
}
我为此定义了 3 个变量,A 为抖动的振幅,speed 为抖动的速度,即抖动频率的控制,x 会按照 speed 定义的速度持续增加。
若判定抖动触发(bool==true),则让⾓⾊ Sprite 的 X 坐标等于 A*Mathf.Cos(x) 的值,借由三⾓函数的函数图像可知,若 x ⼀直递增,坐标便会呈现波动态。
连击预输⼊的实现
我将每⼀个攻击动画都分为了三个区间,并且定义了⼀个 bool 值;
当进⼊到第⼆个(图中黄⾊)区间时,便会开始检测玩家是否按下了攻击键,若按下攻击键,则给 bool 变量赋值 true;到第三个区间时,便会开始检测 bool 值的真假,若为真,则允许动画切换到下⼀个攻击动作。⽽在每个动画的第⼀帧,将 bool 值重新置为 false。
⼀般我会在允许动画切换的关键帧前⾯留 2-3 帧作为预输⼊的区间。
总结
那么,这是最终实现出来的效果:录像软件和 GIF 制作出来的效果不能很好的表达出来……
本次毕设研究主要以视觉表现为主;⼀个合适的⾳效的确能给打击感带来更好的体验,但⼀个好的打击感主要还是通过视觉反馈造就的。玩家在按下按键的⼀瞬间或是按键之前⼼⾥就已经有了相应的预期,⽽产⽣的结果如果符合或超过玩家的预期则证明该反馈是优秀的。
不难理解为什么有⼈只通过看视频就想要对打击感评头论⾜,因为⼈们更在意感官表现,因为那很直观,尽管操作⼿感也包括在打击感的⼀环⾥,但并不是没有仅凭视觉就让⼈称赞的作品。
通过这次毕设的实验,我发现也许打击感更多要靠美术去表现。程序上的实现⼿段总结了下来⼤多都能理解,运⽤得当即可。但我在任何参数都没改变的情况下,仅仅换了⼀整套更⾼质量的美术资源,呈现出来的效果却让我感觉好了很多。上⾯在说明“帧冻结”的时候提到过,⼀次好的打击感也需要有好的动作设计和上乘的美术表现。通过实验,我对此有了较为深刻的印象。
我希望能通过分享和交流学习到更多的东西。
以上这些主要为我的毕业设计中系统开发的⼀部分,有很多地⽅没有说明为何要这样做。希望有机会能将更多的东西整理出来吧。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论