Unity引擎2D游戏开发,实装攻击判定

发布时间 2023-12-20 15:53:07作者: 心霖の雨

判断伤害触发动画帧

观察动画,发现只需要在第4帧时才进行伤害,即发生剑影的那一帧。其他动画同理
image

添加碰撞盒

目前不需要再玩家Player身上建立过多的碰撞体,因为采用新的方式

选中Player,右击选择Create Empty,创建一个子级对象。命名为,Attack Area
image

image

并在Attack Area下方再创建三个子对象,Attack1、Attack2、Attack3
image

选中Attack1,在右侧点击Add Property,添加一个碰撞盒作为触发器,选择Polygon Collider 2D
image

勾选Is Trigger,作为触发器使用
image

点击Edit Collider,将碰撞盒的边界对准剑影的边界
image

此处的碰撞盒作为触发器去判定伤害,只需要在剑影出现的那一帧进行判定。因此,只需要在此帧到达的时候打开此碰撞盒,不在此帧则关闭此碰撞盒

打开或关闭碰撞盒

碰撞盒的伤害判定只需要在合适的动画帧进行,不需要的动画帧不打开碰撞盒

在Animation窗口中,点击Add Property,选择Attack Area下的Attack1中的Game Object.Is Active添加进窗口中
image

选择第一帧,对碰撞盒进行关闭
image

image

选择剑影出现的那一帧,打开碰撞盒,即可打上关键帧
image

同理,在下一帧取消勾选
image

实现攻击伤害

选择Attack1,点击Add Component,添加Attack脚本
image

Damage设置为10,即10点伤害
image

按照上面的方法,将Attack2和Attack3绑定上碰撞盒和Attack脚本

在测试前,一定要先关闭三段攻击的碰撞盒
在测试前,一定要先关闭三段攻击的碰撞盒
在测试前,一定要先关闭三段攻击的碰撞盒

解决剑影的碰撞盒伤害到人物自身的问题

打开剑影的碰撞盒,将Contack Capture Layer选择Enemy层。这样,此碰撞盒只会跟Enemy进行碰撞判定,不会跟自己进行碰撞判定
image

解决人物攻击后,敌人不扣血的问题

由于野猪对象绑定了两种碰撞盒,Layer Override Priority优先级相同,所以无法进行碰撞判定
image

受伤判定的碰撞盒,为胶囊碰撞盒(Capsule Collider 2D)。因此,将它的优先级设置为最高
image

如果上述无效还有一种可能性

因为OnTriggerStay2D有个休眠时间,它被触发一段时间后自动停止。要想再次触发该函数需要稍微移动其中一个碰撞盒,也就是玩家需要移动到不同位置攻击野猪它才会掉血。后面的课程会让野猪动起来,这样这个问题就不存在了。当然也可以修改OnTriggerStay2D的休眠时间,使之变长,这样即使在原地攻击野猪它也会持续掉血。修改OnTriggerStay2D的休眠时间方法:点击Edit -> Project Settings,然后选择Physics 2D,如下图所示,在General Settings中将Time To Sleep修改为一个较大的值,如10000(默认情况下是0.5)
image

解决任务攻击时还能移动的问题

在PlayerController中,FixedUpdate()方法内,添加isAttack的判断

private void FixedUpdate()
{
    if(!isHurt && !isAttack)
    {
        Move();
    }
}

此时发现还是能够移动,并没有彻底解决问题

因为人物现在使用的材质是光滑材质,此前为了解决碰墙无法下落的问题所使用的

创建一个新的材质,并将原来的材质更名为Wall
image

创建的新的材质,将摩擦力(Friction)修改为正常的0.4
image

将有摩擦力的材质拖入人物Capsule Collider 2D的Material
image

此时能够发现已经能有效控制人物的移动,如果不想要每一段攻击后人物向前位移的效果,参考下面所述的方法来解决

处理人物每一段攻击后向前位移的动作

打开AttackFinish文件,在OnStateEnter()方法中,添加以下代码,将isAttack置为true

override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
    animator.GetComponent<PlayerController>().isAttack = true;
}

动态切换人物材质

PlayerController中,添加两个变量,用以初始化材质

[Header("物理材质")]
// 带有摩擦力的普通材质
public PhysicsMaterial2D normal;
// 不带有摩擦力的光滑材质
public PhysicsMaterial2D wall;

编写CheckState()方法,根据情况赋予材质

// 根据人物解除地面或者墙体,动态更改人物的材质
private void CheckState()
{
    capsuleCollider.sharedMaterial = physicsCheck.isGround ? normal : wall;
}

然后在Update()方法中调用

private void Update()
{
    CheckState();
}

最后在Player的Player Controller中拖入创建好的材质。这样才能在运行后自动赋予Player材质
image