将一个对象放在Raycast点,但在Unity3D中考虑了冲突

时间:2016-01-15 14:35:47

标签: c# unity3d collision-detection collision raycasting

我正在尝试将一个对象放在我的Raycast点(Raycast发现碰撞的地方)。但我得到的是你在附图中看到的(2种不同的情况)。该对象放置在我确实指向的位置,但我想考虑碰撞,以便对象不会相互通过。 每个物体都有自己的对撞机。

Two different cases in which objects are positioned through each other

有人知道如何解决这个问题吗?谢谢。

编辑:

我试图像这样实现@ 31eee384给出的解决方案:

RaycastHit hit;
Game.MuebleAEditarGO.transform.position = CameraFacing.transform.position;
if (Game.MuebleAEditarGO.GetComponentInChildren<Rigidbody>().SweepTest(CameraFacing.transform.rotation * Vector3.forward, out hit, 50f))
{
    Game.MuebleAEditarGO.transform.position += CameraFacing.transform.forward * hit.distance;
}

MuebleAEditarGO是一个RigidBody。墙壁(以及一般的房屋)不是刚体,每个都有MeshoColliders。

但后来我得到了部分有效的解决方案。当RaycastHit只发现一次碰撞时,它似乎工作正常(见下图)。

Image showing the problem with rigidbodies and collisions

5 个答案:

答案 0 :(得分:2)

最直接的解决方案是使用Unity的物理引擎:Rigidbody.SweepTest。它用它的碰撞器扫描你的实际刚体(没有像边界框或手动距离检查那样的抽象),它将通过物理引擎可以提供的所有优化和广义计算来实现。

要使用它,请查看SweepTest文档页面上的示例,为了完整性,请复制到此处:

RaycastHit hit;
if (rb.SweepTest(transform.forward, out hit, collisionCheckDistance))
{
    aboutToCollide = true;
    distanceToCollision = hit.distance;
}

然后使用transform.forward * distanceToCollision确定移动对象的距离,直到它首次发生碰撞。例如:

RaycastHit hit;
couch.transform.position = transform.position;
if (couch.SweepTest(transform.forward, out hit, 50f))
{
    couch.transform.position += transform.forward * hit.distance;
}

确保您的物体位于不同的物理层上,这样沙发就不会与玩家的对手发生碰撞。

答案 1 :(得分:1)

您的问题在很大程度上取决于您的规格。 您可以从计算产生GameObject的对撞机的宽度开始并应用偏移量,但它仅在面向平面时才起作用。在目标位置周围添加光线投射也可以让您管理角落。 管理更一般的情况(不规则的表面,小于物体的角落等)将导致更复杂的解决方案。

答案 2 :(得分:0)

利用Unity的OnTriggerEnter OnTriggerExit方法来确定对象是否可以放置在某个位置。

例如,您可以跟踪您放置的对象与之碰撞的对象数量,方法是每当某些内容进入其触发器时将其添加一个数字。然后,当某些东西离开它的触发器时,从该数字中减去一个。如果对象中的对撞机数量为零,则放置对象是安全的。

public class PlaceableObject : MonoBehaviour 
{
    int CollidersInTrigger = 0;

    void OnTriggerEnter(Collider col)
    {
        CollidersInTrigger++;
    }

    void OnTriggerExit(Collider other) 
    {
        CollidersInTrigger--;
    }

    bool CanPlace()
    {
        return CollidersInTrigger == 0;
    }
}

请注意,要使其工作,当您的对象处于“放置模式”时,其对撞机的IsTrigger属性必须设置为true。

答案 3 :(得分:0)

脱离我的头顶:

辐射4 有点方式:

你最有可能引用你持有的对象。附上一个脚本,它将保存一个公共bool变量,以标记它是否在任何给定时刻与任何东西相交。在OnTriggerEnter()和OnTriggerExit()中切换bool的值。如果bool为true,则不允许用户放下对象(并且可能在对象上使用另一层红色或其他东西让他们知道)

Portal 2 方式:

你很可能有一些脚本描述你可以抓住的对象。添加一个大小变量来描述对象的代理大小 - 比一个轴上的最大比例大一点。 (例如,如果沙发是2x5x10大小,请代理为11)

禁用您持有的对象上的对撞机。因此,光线投射将适用于你所看到的其他一切。

如果射线击中任何东西,则使用ray.point。从那一点开始,取一些大于你物体大小的任意值,并将你的物体向你移动。

答案 4 :(得分:0)

据我所知,你的目标是在不同的地方产生不同的物体。

我在这里看到了两种可以组合的方法。

  1. 您有无对象区域并随机生成对象。但是,如果您无法使此区域对象自由,则可能会出现问题。至少你可以查看OverlapSphere或者你的区域是否免费。如果没有,您选择另一个区域来检查并在该区域内的随机位置产卵

  2. 你&#34; drop&#34;你的物体从高处不可能在其他物体内产生。在这一点上,你可以让物体在障碍物前面垂直或垂直位置并产生。