Unity:如何从父脚本检测子对象上发生的冲突?


12

我有一个敌人,这个结构

  • 敌人
    • 身体
      • 左臂
      • 右臂

等等。

我的身体每个部位都有一个对撞机。在我的“敌人”对象中,我附加了一个脚本,在该脚本中,我想截获身体,头部,手臂,左侧等可能发生的碰撞(子弹)。

有没有办法做到这一点?

Answers:


16

如果您将Rigidbody与角色一起使用,则可以立即使用。:)

因此,您的层次结构可能如下所示:

  • 角色(具有刚体和控制脚本)
    • 孩子(可能有对撞机)
      • 孙子(也许有对撞机)

OnCollisionEnter消息将在包含刚体的GameObject上触发,到达您的父控制脚本,而无需编写额外的中继脚本来粘贴在每个对撞机上。

如果您需要找出发生碰撞的是哪个儿童对撞机,可以这样进行:

void OnCollisionEnter(Collision collision) {
    Collider myCollider = collision.contacts[0].thisCollider;
    // Now do whatever you need with myCollider.
    // (If multiple colliders were involved in the collision, 
    // you can find them all by iterating through the contacts)
}

5

解决此问题的一种方法是使用两个脚本:一个用于Enemy对象,另一个用于子对象(您需要将其分配给Enemy obj的子对象)

父脚本

using UnityEngine;

 public class ParentScript : MonoBehaviour 
 {
     public void CollisionDetected(ChildScript childScript)
     {
         Debug.Log("child collided");
     } 
 }

子脚本

using UnityEngine;

public class ChildScript : MonoBehaviour 
{
     void OnCollisionEnter(Collision collision)
     {
         transform.parent.GetComponent<ParentScript>().CollisionDetected(this);
     }
 }

这样,当孩子发生碰撞时,您应该得到通知


2
如果您使用这样的解决方案,并且发生了很多冲突,我强烈建议让孩子们缓存其接收方父母的GameObject。每当您要多次调用相同的GetComponent时,这都是一个好习惯,它使您可以进行任何棘手的“查找要发送给该链的父对象”逻辑,只需执行一次即可。还要记住,transform.parent将仅获得直接父级。
鲁宁

2

您可以简单地将顶层对象传递给子对象,然后直接在子对象上调用函数。这样可以确保您不必依赖父传播。所以你最终不会做一些愚蠢的事情transform.parent.parent

但是,您可以使用GetComponentInParent自动执行此过程。这将检索找到的第一个脚本。然后将其缓存在碰撞对象中,直接在该缓存对象上调用函数。

或者,您可以利用UnityEvents(不使用Messages)将函数绑定到子对象。使用unity事件,您可以添加任何任意的侦听器,因此您不仅可以将被击中的子对象通知顶级对象,还可以做更多的事情。


1

来自Unity Answers(由Ashish Dwivedi撰写)的直接报价

向子级添加脚本,并且在其内部具有父对象脚本的引用。现在在父脚本中编写3个方法,例如(OnCollisionEnter2DChild,OnCollisionStay2DChild,OnCollisionExit2DChild),并通过传递碰撞对象从子对象脚本中的方法(OnCollisionEnter2D,OnCollisionStay2D,OnCollisionExit2D)中调用相应的方法。


1

您可以检查碰撞并查看哪个命中框被击中,并在需要时获得碰撞点。

注意:刚体放置在具有“碰撞检查”脚本的同一对象上。

本示例正在检查“弹丸”命中哪个命中目标。

private void OnCollisionEnter(Collision collision)
{                 
    if (collision.contacts[0].otherCollider.transform.gameObject.name == "HeadShot")                
       //DO STUFF            

    if (collision.contacts[0].otherCollider.transform.gameObject.name == "BodyShot")
       //DO STUFF    
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.