从Physics.ComputePenetration()获取碰撞点

问题描述 投票:0回答:2

我在 Unity 中有一个非常基本的播放器,我编写了它来使用

Physics.ComputePenetration(...)
与对象进行碰撞,并且效果相对较好。问题是我想要有关玩家撞到碰撞体的哪里的更多详细信息。

一些注意事项:

首先,这个项目的想法是看看我是否可以使用

CharacterController
从头开始复制
ComputePenetration
的功能。我目前正在尝试复制内置的
OnControllerColliderHit(...)
函数,它允许我获取命中发生的位置。

其次,我没有使用

SphereCollider
。如果是的话,那么我所要做的就是获取返回的
direction
向量并将其乘以球体的半径(以及其他一些东西)。但遗憾的是,我正在使用
CapsuleCollider
(也许有一种方法可以做同样的事情,但对于
CapsuleCollider
,但我还没有找到)。

我尝试过的:

我最初的想法是采用玩家击中的碰撞器

hitCollider
,并执行以下代码片段:

Vector3 point = hitCollider.ClosestPoint(player.transform.position);

获取碰撞对撞机上最近的点。从那里我可以打电话

Vector3 finalPoint = player.collider.ClosestPoint(point);

在玩家上获得最接近碰撞对撞机的最近点。这很令人困惑,但效果很好。然而,只有一个缺点:我计划使用 ProBuilder 进行大量关卡设计,并且您无法在未将

ClosestPoint
设置为 true(大多数网格体)的
MeshCollider
上调用
convex
在 ProBuilder 中。

我想到了其他一些事情,比如也许我可以反转方向,然后做一些(不那么)黑客数学来获得接触点等,但似乎没有什么可以作为成熟的解决方案。

结束语:

我开始认为这在技术上是不可能的。如果你仔细想想,这是真的,因为当两个对象相交时,没有单个来定义它,而是一个完整的体积来定义它。但获得该交易量的平均位置将(也许?)是解决方案。

有什么想法吗?

提前谢谢您!

c# unity-game-engine game-physics physics-engine physx
2个回答
2
投票

对于其他好奇的人,我找到了解决方案。当

Physics.ComputePenetration(...)
ourCollider
之间的
selectedCollider
检测到碰撞时,请确保首先进行反渗透,然后执行以下操作:

调用

Physics.CapsuleCast(...)
,但确保
point1
point2
radius
的值略小于原始胶囊的大小(可能是 0.001)。这是因为
CapsuleCast
会认为它与
selectedCollider
相交,因此会直接穿过它,这是您不希望的。然后只需将
direction
设为从
Physics.ComputePenetration(...)
输出的负方向即可。

所以你的代码最终看起来像这样:

var origin = this.transform.position + this.center;
var offset = new Vector3(0.0f, this.height / 2.0f - this.radius - someTinyValue, 0.0f);
if (Physics.CapsuleCast(
        origin + offset,
        origin - offset,
        this.radius - someTinyValue,
        -direction,
        out var hit))
{
    // Do whatever with the `hit` variable
}

0
投票

这个方法效果很好,但可能有点慢。 (至少我有时会看到瞬间的交叉点)

public bool IsGrounded { get; set; } = true;
private void OnTriggerEnter(Collider other)
{   
    if (other.CompareTag(_groundTagName))
    {
        IsGrounded = true;
        _landingSpeed = _fireSpeed;

        if(_IsPhysicsComputePenetration == true)
        {   //Here is the exact point to calculate intersection level
            //Player collider and transformation infos, other collider and transformation infos required to find exact intersection vector and scale
            Physics.ComputePenetration(_collider, transform.position, transform.rotation,
                       other, other.transform.position, other.transform.rotation,
                       out _penetrationDirection, out _penetrationDistance);
            Debug.Log("Grounded!");
            AlignGameObjectToSurfaceAfterCollision();
        }

    }
}

private void AlignGameObjectToSurfaceAfterCollision()
{   
    transform.position += _penetrationDirection * _penetrationDistance;
}
© www.soinside.com 2019 - 2024. All rights reserved.