引言:在完成了普通攻击的四段连击之后,笔者将继续实现玩家的攻击在敌人身上产生的反馈,并且攻击分为Light和Heavy,Heavy攻击将击退敌人
首先需要将Attack业务分离出来,声明AttackController类,并且挂载在一个空物体上,让空物体作为玩家手部或者携带武器部位的root上,如下:
之后笔者将通过attackRange这个物体来进行攻击判定,常见的攻击判断方式分为距离检测、碰撞检测、射线检测等,笔者选择较为简单的碰撞检测,在attackRange上挂载碰撞体,在动画中打开与关闭碰撞。碰撞设置好之后,继续声明攻击信息结构体,该结构体将包含需要传递给受击方所需的数据,包括攻击名称、攻击倍率、受击方将受到的击退力的大小,并且用[Serializable]使得其可以直接在inspector中进行编辑
/// <summary>
/// attack info
/// </summary>
[Serializable]
public struct AttackInfo
{
public string AttackName;
public float DamageRate;
public float ForceValue;
}
之后在AttackController类中声明一个AttackInfo[]
public AttackInfo[] attackInfos;
在inspector中编辑好相关数据
之后继续创建敌人,声明CharacterBase基类
using UnityEngine;
using DG.Tweening;
[RequireComponent(typeof(Rigidbody))]
public class CharacterBase : MonoBehaviour
{
public virtual void Damage(AttackInfo attackInfo, Vector3 pos)
{
Debug.Log("hit suc! " + attackInfo.AttackName);
transform.GetComponent<Animator>().Play("Hit_F");
//damage offset
DamageOffset(attackInfo, pos);
}
public virtual void DamageOffset(AttackInfo attackInfo, Vector3 pos)
{
//offset vector
Vector3 offsetVec = (transform.position - pos).normalized;
//add offset
transform.DOMoveX(transform.position.x + offsetVec.x * attackInfo.ForceValue, 0.1f);
transform.DOMoveZ(transform.position.z + offsetVec.z * attackInfo.ForceValue, 0.1f);
}
}
任何角色受击后都会播放受击动画(后面再迭代),并且产生位置偏移,偏移量由attackInfo里面的数据决定,笔者采用Dotween来做平滑偏移。之后声明一个Enemy类,继承自CharacterBase即可
public class Enemy : CharacterBase
{
}
继续在AttackController类中写碰撞检测:
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Enemy"))
{
//play hit vfx
hitVfx.transform.position = other.ClosestPoint(transform.position);
hitVfx.Play(true);
//trigger time stop
TimeStopEvent.Trigger();
//get attack info
AttackInfo attackInfo = new();
foreach (var info in attackInfos)
{
if (animator.GetCurrentAnimatorStateInfo(0).IsName(info.AttackName))
{
attackInfo = info;
break;
}
}
//enemy damage
other.gameObject.GetComponent<Enemy>().Damage(attackInfo, animator.transform.position);
}
}
成功触发之后,通过当前播放动画的名称,遍历attackInfos中的attackName找到应当传给受击方的attackInfo,执行受击者身上的Damage方法,加入顿帧和VFX,最终效果如下:
感谢阅读