Unity引擎2D游戏开发,受伤及死亡的逻辑和动画

发布时间 2023-12-26 16:44:42作者: 心霖の雨

裁切素材制作受伤动画

制作死亡动画

由于没有死亡动画素材,所以直接调整Alpha通道数值,使其逐渐消失

Animations中复制野猪受伤动画,命名为boarDead
image

Animator中拖入boarDead动画
image

点击Add Property,选择Color
image

将最后一帧的Alpha值改为0
image

Animator连接动画逻辑

从Any State连接至这两个创建好的boarDeadboarHurt动画,再将Hurt连接至Exit
image
受伤和死亡可以从任意一个状态切入

boarHurt的连接线,设置为动画完整播放一次后退出
image

野猪受击转换方向

在Enemy中创建一个新的全局变量

public Transform attacker;

创建一个OnTakeDamage()方法,通过攻击者和受击者的X轴差值来判定攻击者在左在右,使野猪掉换方向

public void OnTakeDamage(Transform attackTrans)
{
    attacker = attackTrans;
    if(attackTrans.position.x - transform.position.x > 0)
    {
        transform.localScale = new Vector3(-1, 1, 1);
    }
    if (attackTrans.position.x - transform.position.x < 0)
    {
        transform.localScale = new Vector3(1, 1, 1);
    }
}

野猪受伤被击退

OnTakeDamage()方法中添加一下代码

// 受伤被击退
isHurt = true;
animator.SetTrigger("hurt");
// 记录被攻击的方向
Vector2 dir = new Vector2(transform.position.x - attackTrans.position.x, 0).normalized;
StartCoroutine(OnHurt(dir));

StartCoroutine为启动协程,需要搭配IEnumerator使用

StartCoroutine官方文档:https://docs.unity3d.com/cn/2022.3/ScriptReference/MonoBehaviour.StartCoroutine.html

编写IEnumerator OnHurt()协同程序方法

private IEnumerator OnHurt(Vector2 dir)
{
    // 施加瞬时力
    rb.AddForce(dir * hurtForce, ForceMode2D.Impulse);
    yield return new WaitForSeconds(0.45f);
    isHurt = false;
}

IEnumerator:标记为协同程序,此方法代码会一行一行阻塞顺序执行
yield return:顺序迭代器,可选择等待固定模式后再执行下一步

野猪死亡代码逻辑并销毁

Enemy中创建新的全局变量

public bool isDead;

并创建一个OnDie()方法,将动画的Dead条件以及isDead设置为true

public void OnDie()
{
    animator.SetBool("dead", true);
    isDead = true;
}

编写DestroyAfterDeadAnimation()销毁对象的方法

public void DestroyAfterDeadAnimation()
{
    Destroy(this.gameObject);
}

接着,在Boar对象的Animation窗口,移动到最后一帧,添加一个Animation Event
image

将该Event绑定DestroyAfterDeadAnimation()方法
image

解决销毁后仍有碰撞体积的问题

取消勾选此处的勾,代表Player不与Ignore Raycast层碰撞
image

在Layer中,我们能发现Ignore Raycast层序号为2
image

在Enemy的OnDie()方法中,将Enemy层赋值为2

public void OnDie()
{
    gameObject.layer = 2;
    animator.SetBool("dead", true);
    isDead = true;
}