我的 FPS 项目中的子弹碰撞问题相当多。也就是说,有时,子弹会记录碰撞,有时却不会。看来两者之间的差异恰好与我们站在自己和目标之间的位置有关,但有时情况并非如此(即我们稍微移动回刚刚射击的同一位置并发生碰撞)可能会再次工作)。
为了简单地解决这个问题,我将留下一个链接,指向我针对此问题所做的大量 Reddit 帖子:https://www.reddit.com/r/Unity3D/comments/18g4dr8/comment/ke7x2k7 /?上下文=3
问题的当前状态是该错误仍然有效,并且自我上次测试以来没有任何真正的改变。如果你们需要有关此事的更多信息,请告诉我。
在不知道您当前的代码的情况下,我很难判断,但对我来说,这听起来像是“隧道”的情况。您可以在[此处]找到非常好的解释(https://gamedev.stackexchange.com/a/192403)。
简而言之:您的物体在一帧中仍然位于碰撞物体的前面,而在下一帧中则位于碰撞物体的后面。所以它实际上永远不会碰撞/触发。
在 Unity 中,有多种方法可以解决这个问题。我将介绍两个最简单和常见的。在大多数情况下,光线投射方法是最好的方法。
持续碰撞
调整物体的碰撞器设置,将“碰撞检测”属性设置为“连续”或“连续动态”,这样Unity就可以进行更准确的碰撞检查,特别是对于快速移动的物体这是必要的。
光线投射
基本上,您必须从最后一帧到当前帧位置执行光线投射,以避免隧道问题。这样光线就会击中上一帧和本帧之间的所有物体。示例:
using UnityEngine;
public class Bullet : MonoBehaviour
{
private Vector3 lastPosition;
private float bulletSpeed = 1000.0f;
void Start()
{
lastPosition = transform.position;
}
void Update()
{
lastPosition = transform.position;
// Move the bullet to its next position
transform.Translate(transform.forward * Time.deltaTime * bulletSpeed);
// Perform raycast from last position to current position
CheckForCollisions();
}
void CheckForCollisions()
{
// Calculate the direction the bullet moved
Vector3 movedVector = transform.position - lastFramePosition;
// Cast a ray from the last position to the current position
// `QueryTriggerInteraction.Collide` including triggers
RaycastHit hit;
if (Physics.Raycast(lastPosition, movedVector.normalized, out hit, movedVector.magnitude, QueryTriggerInteraction.Collide))
{
HandleCollision(hit.collider);
}
}
void HandleCollision(Collider otherCollider)
{
Debug.Log("Bullet hit: " + otherCollider.gameObject.name);
Destroy(gameObject);
}
}