如果在武器上使用碰撞盒,使用ontriggerenter 的方式触发击中的话, 在有些攻击动作,帧与帧之间的动作太大,会导致触发失效,如下图 26-27帧之间的动作幅度很大.
虽然我们可以增大碰撞盒子,但这不是一定有效的方案
解决方案
采用射线检测的方式
攻击时,保存射线点这一帧的位置,然后在下一帧时,从上一帧发出射线到当前这一帧.
代码:
public class WeaponRayTest : MonoBehaviour
{
public Transform pointA;
public Transform pointB;
public LayerMask layer;
int hitCount;
public Transform[] Points; //射线发射点
public Dictionary dic_lastPoints = new Dictionary(); //存放上个位置信息
public GameObject particle;//粒子效果
private void Start()
{
if (dic_lastPoints.Count == 0)
{
for (int i = 0; i < Points.Length; i++)
{
dic_lastPoints.Add(Points[i].GetHashCode(), Points[i].position);
}
}
}
private void LateUpdate()
{
var newA = pointA.position;
var newB = pointB.position;
Debug.DrawLine(newA, newB, Color.red, 1f);
SetPostion(Points);
}
void SetPostion(Transform[] points)
{
for (int i = 0; i < points.Length; i++)
{
var nowPos = points[i];
dic_lastPoints.TryGetValue(nowPos.GetHashCode(), out Vector3 lastPos);
//Debug.DrawLine(nowPos.position, lastPos, Color.blue, 1f); ;
Debug.DrawRay(lastPos, nowPos.position- lastPos, Color.blue, 1f);
Ray ray = new Ray(lastPos, nowPos.position - lastPos);
RaycastHit[] raycastHits = new RaycastHit[6];
Physics.RaycastNonAlloc(ray, raycastHits, Vector3.Distance(lastPos, nowPos.position), layer, QueryTriggerInteraction.Ignore);
foreach (var item in raycastHits)
{
if (item.collider == null) continue;
//下面做击中后的一些判断和处理
//比如扣血之类的,
//需要注意:在同一帧会多次击中一个对象
Debug.Log(item.collider.name);
if (particle)
{
var go = Instantiate( particle, item.point,Quaternion.identity);
Destroy(go, 3f);
}
hitCount++;
break;
}
if (nowPos.position != lastPos)
{
dic_lastPoints[nowPos.GetHashCode()] = nowPos.position;//存入上个位置信息
}
}
}
private void OnGUI()
{
var labelstyle = new GUIStyle();
labelstyle.fontSize = 32;
labelstyle.normal.textColor = Color.white;
int height = 40;
GUIContent[] contents = new GUIContent[]
{
new GUIContent($"hitCount:{hitCount}"),
new GUIContent($"frameCount:{Time.frameCount }"),
};
for (int i = 0; i < contents.Length; i++)
{
GUI.Label(new Rect(0, height * i, 180, 80), contents[i], labelstyle);
}
}
}
武器绑定:
这里每个点都对应射线发出的位置
运行效果:
运行效果图time.scale 为0.25 ,所以看上去检测射线密集.
红线:代表的武器位置,每个每个节点就是射线点的位置
蓝线:代表射线发出的位置,如果期间有检测到对象,视为击中.
参考:【UE4】游戏中近战攻击判定检测(一)——射线检测!_WadaFak的博客-CSDN博客_ue4攻击判定
射线参考:Unity - 射线检测 - SouthBegonia - 博客园 (cnblogs.com)
性能参考:Unity中各类物理投射性能横向比较 - HONT - 博客园 (cnblogs.com)



