从 OnTriggerXXX 函数中获取 ContactPoint2D/contact normal

Posted

技术标签:

【中文标题】从 OnTriggerXXX 函数中获取 ContactPoint2D/contact normal【英文标题】:Get ContactPoint2D/contact normal from the OnTriggerXXX function 【发布时间】:2018-01-28 15:57:00 【问题描述】:

我试图强制 Unity 在碰撞后不改变物体的速度和方向。我需要得到OnCollisionEnter2D 事件,但不需要Unity 自动改变速度和方向;我想手动完成。

我尝试使用此代码,但不起作用(自动碰撞仍然有效):

private void OnCollisionEnter2D(Collision2D collision)

    fallVector = GetRigidbody.velocity.normalized;
    fallNormalVector = collision.contacts[0].normal;

    var reflectedVelocity = Vector3.Reflect(fallVector, fallNormalVector).normalized;
    GetRigidbody.velocity = reflectedVelocity * 3;        

有人告诉我将我的 GameObject 标记为 isTrigger 并在我的 other 问题中使用 OnTriggerEnter2D,但它使用 Collider2D 而不是 Collision2D,因此我无法正常联系。

如何在OnTriggerEnter2D 函数中从Collider2D 获取ContactPoint2D 或正常联系方式?

编辑:

看完下面的答案,我在下面写了这段代码,但是GetContacts()在所有元素中返回(0.0, 0.0),我做错了什么? 碰撞的两个对象 IsTrigger = true。 (Unity版本为5.6.0f3)

ContactPoint2D[] contacts = new ContactPoint2D[2];

void OnTriggerEnter2D(Collider2D collision)

    //Get all contact points and save to the contacts array variable
    collision.GetContacts(contacts);

    Vector3 normal = contacts[0].normal;

    GetRigidbody.velocity = Vector3.Reflect(GetRigidbody.velocity, normal);

【问题讨论】:

isTrigger = true 的碰撞器不返回接触点。到目前为止,似乎没有简单的方法可以在不编写一些自定义光线投射代码的情况下获得与普通碰撞器相同的接触点,而且对于非平凡的碰撞器形状很难做到这一点。 【参考方案1】:

我不能使用 OnTriggerEnter2D - 它没有 Collision2D 可定义 正常联系

普通变量来自ContactPoint2D 结构,您可以OnCollisionEnter2D 代码转换为OnTriggerEnter2D,并且仍然能够使用Collider2D.GetContacts 函数检索该信息。

您必须拥有 Unity 5.6 及更早版本才能使用此功能。如果您没有此版本,请不要说“它不起作用”,因为它不应该。您需要更新才能获得此功能。

有碰撞

void OnCollisionEnter2D(Collision2D collision)

    Vector2 normal = collision.contacts[0].normal;
    Vector2 point = contacts[0].point;

触发器等效项

//Variable to hold the contacts
ContactPoint2D[] contacts = new ContactPoint2D[2];

void OnTriggerEnter2D(Collider2D collision)

    //Get all contact points and save to the contacts array variable
    collision.GetContacts(contacts);

    Vector3 normal = contacts[0].normal;
    Vector2 point = contacts[0].point;

罢工>

请确保首先将碰撞器标记为触发器,正如我在other 回答中所说的那样。函数代码中唯一需要更改的是fallNormalVector = collision.contacts[0].normal;

编辑/更新:

你不能再这样做了或发生了一些变化。这篇文章是使用 Unity 5.6 制作的,并且在测试时有效。当时的Collider2D.GetContactsdocumentation并没有说collider被标记为isTrigger时不起作用。最新的documentation说做不到。

涉及将 Collider2D 设置为触发器的联系人将永远不会 此处返回,因为触发对撞机没有接触点。

这是在发布之前经过测试的,它运行良好,现在我怀疑它在 Collider 被标记为 isTrigger 时运行时是一个错误。 要使用Collider2D.GetContacts,请确保您的碰撞器没有标记为isTrigger

【讨论】:

你试过这个代码吗?我所有的实验、谷歌搜索和 Unity 文档片段都表明,如果一个或两个对撞机是触发器,那么它不会提供接触点。 collision.GetContacts() 然后返回 0 的计数。 @angularsen 我在发布之前确实对其进行了测试。在发布之前,我在答案中测试了 99% 的代码。有关更多信息,请参阅我的编辑。【参考方案2】:

我相信您的 GetContacts 代码行为正确,但是 based on the ContactPoint2D documentation,触发器不会生成联系点。如果您要运行int count = other.GetContacts(contacts);,则应将count 变量设置为零。

【讨论】:

【参考方案3】:

您可以用来获得一个点接近到碰撞点的一种方法是使用collider2D.ClosestPoint(transform.position)。这将在对撞机上获得一个最接近当前变换位置的点。

这种方法可能不准确,但根据用例可能足够好。

https://docs.unity3d.com/2019.1/Documentation/ScriptReference/Collider2D.ClosestPoint.html

【讨论】:

以上是关于从 OnTriggerXXX 函数中获取 ContactPoint2D/contact normal的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery:标准 SQL 和 PERCENTILE_CONT() 函数

如何在 select 语句中包含 PERCENTILE_CONT 列,而不会生成有关 ORDER BY 子句或聚合函数的错误?

在 Vertica 中创建 percentile_cont 作为聚合函数

百度ueditor编辑器如何显示、修改从数据库中的数据?

Eclipse 找不到/加载主类

如何从对象的规范名称中获取用户主体名称