Unity武器与子弹碰撞检测 您所在的位置:网站首页 unity碰撞体怎么设置消失 Unity武器与子弹碰撞检测

Unity武器与子弹碰撞检测

2024-02-10 15:25| 来源: 网络整理| 查看: 265

Unity武器与子弹碰撞检测 一、采用碰撞器和刚体进行碰撞检测二、使用代码检测

在想进行碰撞检测制造伤害或生成特效时,有两种常用的方法,一种是使用碰撞器和刚体,检测到碰撞后会自动调用OnCollisionEnter等函数,一种是使用Physics接口下的OverlapBox等检测函数。

一、采用碰撞器和刚体进行碰撞检测

在使用Collider进行碰撞检测时,至少要有一方是带有刚体组件。在默认设置的情况下这样就能够进行碰撞检测,但是在设置物体为静态或勾选刚体的动力学选项后会有不同。 关于这两种碰撞什么情况下可以检测到请看该链接

不关心碰撞位置的情况:

可以把碰撞检测方的碰撞器设置为IsTrigger,并在碰撞组件同级挂载碰撞检测后调用的代码。把碰撞器设置为IsTrigger后,能检测到碰撞并且调用OnTriggerEnter,OnTriggerStay,OnTriggerExit,但是不会对双方造成物理作用。

/// /// 进入碰撞范围时自动调用 /// /// 碰撞检测到的物体,以下简称目标物 private void OnTriggerEnter(Collider other) { // owner是持有武器的角色身上的碰撞器,目标物的碰撞体为拥有者的碰撞体时直接返回 if (other.GetInstanceID() == owner.GetInstanceID()) return; // 判断目标物是否为可以被攻击的物体 Controller entity; if (!other.TryGetComponent(out entity)) return; // 调用目标物的受到伤害的函数 entity.TakeDamage(1); }

关心碰撞位置的情况:

有时可能需要碰撞的位置来生成特效,比如子弹打中哪里就在哪里生成击中特效,在OnTriggerEnter中做不到这一点,当然也能在此时碰撞体所在的位置生成特效,但位置仍是不准确的。 此时不能把碰撞器设置为IsTrigger,因为需要使用OnCollisionEnter函数,同样在碰撞组件同级挂载碰撞检测后调用的代码。

/// /// 进入碰撞范围时自动调用 /// /// 碰撞检测到的物体,以下简称目标物 private void OnCollisionEnter(Collision collision) { // 发生碰撞的位置 Vector3 hitPoint = collision.contacts[0].point; // 实例化特效 GameObject hitEffect = Instantiate(effectPrefab); // 将特效放置在碰撞点 hitEffect .transform.position = hitPoint; }

如果想要更精确的模拟击中特效,可以将生成的特效的方向改为碰撞体的反方向,比如子弹击中后,血液往子弹来的方向喷。

二、使用代码检测

在这里插入图片描述 Physics接口中有许多碰撞检测的函数可以调用,每个函数的返回值和参数都不一样,但用法大同小异,这里就拿OverlapBox作为例子。

// 进行检测的层级,暴露在属性页面进行勾选 [SerializeField] LayerMask impactLayer; // 碰撞检测的物体 [SerializeField] Transform colBox; private void Update() { BoxCheck(colBox); } /// /// 箱型检测 /// /// 箱子物体,可以空物体,作为武器的子物体跟随移动 void BoxCheck(Transform colBox) { // 检测中心点 Vector3 center = colBox.position; // 碰撞器的缩放,以Unity默认的正方体为标准 Vector3 checkBox= new Vector3(1, 0.1f, 0.1f); // 碰撞检测到的碰撞体 Collider[] colliders = Physics.OverlapBox(center, checkBox, colBox.rotation, impactLayer); foreach (var col in colliders) { // 碰撞体是自身 if (col.GetInstanceID() == owner.GetInstanceID()) continue; // 判断目标物是否为可以被攻击的物体 Controller entity; if (!col.TryGetComponent(out entity)) continue; // 调用目标物的受到伤害的函数 entity.TakeDamage(1); } }

用代码检测碰撞时不需要刚体组件,但与OnTriggerEnter一样获取不到碰撞位置。

在使用武器攻击敌人时,如果不对敌人的碰撞体进行记录,会产生多段伤害,因为每一帧都在调用碰撞检测,所以上面的代码需要进行优化。

1、只在武器挥出的时候进行检测,可以在动画里设置帧事件,在攻击动作的前后设置开启和关闭 2、标记碰撞体以避免重复检测

// 已经被伤害过的碰撞体 HashSet colsMarked = new HashSet(); //是否开启碰撞检测 bool enableDamage; private void Update() { if (!enableDamage) return; BoxCheck(colBox); } /// /// 箱型检测 /// /// 箱子物体,可以空物体,作为武器的子物体跟随移动 void BoxCheck(Transform colBox) { // 检测中心点 Vector3 center = colBox.position; // 碰撞器的缩放,以Unity默认的正方体为标准 Vector3 checkBox= new Vector3(1, 0.1f, 0.1f); // 碰撞检测到的碰撞体 Collider[] colliders = Physics.OverlapBox(center, checkBox, colBox.rotation, impactLayer); foreach (var col in colliders) { // 碰撞体是自身 if (col.GetInstanceID() == owner.GetInstanceID()) continue; // 判断目标物是否为可以被攻击的物体 Controller entity; if (!col.TryGetComponent(out entity)) continue; // 向HashSet添加成功时返回True,否则返回False // 返回False时说明已经被添加过了,不能再次造成伤害 if (!colsMarked.Add(col.GetInstanceID())) continue; // 调用目标物的受到伤害的函数 entity.TakeDamage(1); } /// /// 清空标记,可以通过动画帧事件进行调用 /// /// 是否开启碰撞检测 public void EnableDamage(bool enable) { // 清空标记过的碰撞体 colsMarked.Clear(); // 开启或关闭检测 enableDamage = enable; } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有