Unity小白: 简单地 做伤害判定(重投原创)
为了实现自己想要的功能而在网上找七找八,有时毫无头绪,只能无能狂怒。

转入主题:如何使用unity做伤害判定?
做伤害判定有许多种方式,如Trigger、刚体碰撞、RayCast等,不过这次我们要运用BoxCastAll。
BoxCastAll的原理很 简 单 :在指定坐标发射一条射线,射线末端是一个方形的检测区域的中心,然后返回射线与检测区域的所有检测信息。 其API如下:

注:检测区域的大小是2倍的输入值,示意图如下

了解了这些,我们就可以开始了。
打开你的unity。
新建两脚本,分别取名为RoleHP、Projectile:

给Projectile添加变量:
public Transform 子弹根;
//在子弹执行隔帧检测修补时,检测将以上一帧投射部坐标即lastPos为起点,终于当前子弹头部坐标
public Transform 子弹头部;
public Transform 投射部;
public float 速度;
public float 下坠;
//BoxCastAll检测盒体的大小
public Vector3 检测范围;
public LayerMask 检测层级;
public float 距离;
List<RoleHP> HitHP;
Collider HitObj;
float correct;
public bool Gizmo;
Transform gizmoObj;
Quaternion quat;
Vector3 lookAt, speed, lastPos,castArea,投射原点;

在update中设置子弹的运动

注:此处的Time.deltaTime解释为 增量时间,其数值为 1/当前的每秒帧数;假设游戏运行时,1秒是N帧,也就是播放了60个画面,执行完,耗时1秒。
x米=(增量时间 * 1秒总帧数)秒 *10米/秒
这样无论帧率是多是少,设置物体1秒移动几米,子弹每秒移动的距离就是几米
若不按照以上的方式进行移动,那么在帧率不同的时候,物体移动的速度可能也会随之变化
既然有帧率,那么物体的移动就是有 间隔 的:

因此,如果物体的移动速度过快,则会出现检测不到子弹正常轨道上的物体的情况;同理,有时候游戏中角色移动过快就会出现无视碰撞地穿墙。
新增 纠正检测 函数,然后在移动代码的后方进行引用:
private void 纠正检测()
{
castArea = 检测范围;
correct = Vector3.Distance(子弹头部.position, lastPos);
lookAt = Vector3.Normalize(子弹头部.position - lastPos);
if (correct > 检测范围.z)
{ //进行补帧检测
投射原点 = lastPos;
castArea.z = correct;
}
else
{ //保持原检测范围不变
投射原点 = 投射部.position;
castArea.z = 检测范围.z;
}
}

继续在Update里添加 检测 的代码:
quat = Quaternion.LookRotation(lookAt);
quat.eulerAngles =new Vector3(quat.eulerAngles.x,quat.eulerAngles.y,子弹根.rotation.eulerAngles.z) ;
Hits = Physics.BoxCastAll(投射原点, castArea / 2, lookAt, quat, castArea.z / 2, 检测层级);
foreach (var hit in Hits)
{
判断攻击的逻辑靠你们自己写了...............
}

代码原理如下:
接着:执行运动代码,子弹正式开始移动,然后子弹的位置开始变化。此时,update的代码就运转到 纠正检测函数。虽然子弹的位置产生变化,变量lastPos记录的还是子弹 上 一 帧 的位置,以此就可以“获取上一帧位置”。用vector3.distance获取当前帧与上一帧的距离
(此处“lookAt”=子弹头部.position - lastPos 是为了 获 取 lastPos朝向子弹头部.position的方向)。
代码运转到了BoxCastAll部分,检测投射从lastPos中发出,射线距离等于检测范围的z轴(这样做的原因是为了让方盒检测范围充当主要检测部分,射线暂时不需要),从“上一帧坐标”朝向当前坐标。这里填写的“quat”是一个quaternion(四元数),用来调整检测盒体的旋转方向(重头戏):
BoxCastAll的旋转是需代码更改的,它不会无端端受任何物体的影响。
理想状态下,方盒的起始点是lastPos,终点是投射部.position。因此其quat = LookRotation(lookAt) .............这就完了吗?
不,如果你想要检测再精密一点,这个盒体的z轴就要与子弹根的z轴一致。因此子弹在围绕Z轴旋转时,检测盒体也会跟着旋转
代码为 quat.eulerAngles = new Vector3(quat.eulerAngles.x, quat.eulerAngles.y, 子弹根.rotation.eulerAngles.z);
然后检测到的物体只能是指定层级且带有碰撞体组件的。
待获取检测信息后,foreach (var hit in Hits)会从所有检测到的物体中遍历每个检测到的物体。若有物体满足条件: 该物体没有在 List数组“所有击中物”之内,且包含脚本“HP”。则该物体可以被赋予伤害,然后调用其脚本“HP”上的伤害函数。然后添加该物体至 List数组“所有击中物”之内。最后就用lastPos = transform.position; 来更新“上一帧位置”,以便下一帧update的继续调用。
//忘记加子弹延时销毁了,请大家需要的自行加上。
如果你还是听不懂我的十级鬼语的,那么就让可视化的Gizmos来告诉你吧!
(使用时要保证子弹根即其以上的父物体的scale值为1,1,1哦! 不然Gizmos会有误差的!)
在Resources文件夹(无则新建)下新建一个预制体名为Gizmos。
给Gizmos添加一个子物体方盒,其z轴前进0.5个单位

然后添加如此代码


注,这样子 生成的gizmos物体除编辑窗口外是看不见的哦!
(作者自鞭,这应该是受到了新建图层的影响)
然后别看了!写你的代码去吧!