C# 将对象放置在光线投射点处,但在Unity3D中考虑碰撞

C# 将对象放置在光线投射点处,但在Unity3D中考虑碰撞,c#,unity3d,collision-detection,collision,raycasting,C#,Unity3d,Collision Detection,Collision,Raycasting,我正在尝试将对象放置在光线投射点的位置(光线投射发现碰撞的位置)。但我得到的是你在所附图片中看到的(两种不同的情况)。物体确实被放置在我指向的地方,但我想考虑碰撞,这样物体就不会互相穿过。 每个物体都有自己的对撞机 有人知道怎么解决这个问题吗?多谢各位 一月 编辑: 我试图实现@31eee384给出的解决方案,如下所示: RaycastHit hit; Game.MuebleAEditarGO.transform.position = CameraFacing.transform.positi

我正在尝试将对象放置在光线投射点的位置(光线投射发现碰撞的位置)。但我得到的是你在所附图片中看到的(两种不同的情况)。物体确实被放置在我指向的地方,但我想考虑碰撞,这样物体就不会互相穿过。 每个物体都有自己的对撞机

有人知道怎么解决这个问题吗?多谢各位

一月

编辑:

我试图实现@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;
}
raycastthit;
Game.MuebleAEditarGO.transform.position=CameraFacing.transform.position;
if(Game.MuebleAEditarGO.getComponentChildren().SweepTest(CameraFacing.transform.rotation*Vector3.forward,out hit,50f))
{
Game.MuebleAEditarGO.transform.position+=CameraFacing.transform.forward*hit.distance;
}
MuebleAEditarGO是一个刚体。墙壁(以及整个房子)不是刚体,它们各自都有网格准直器

但我得到了一个部分有效的解决方案。当RaycastHit仅找到一个碰撞时,它似乎工作正常(请参见下图)


您的问题在很大程度上取决于您的规格。 你可以从计算生成游戏对象的碰撞器的宽度开始,并应用一个偏移量,但它只在面对平面时起作用。在目标位置附近添加光线投射也将允许您管理角点。
管理更一般的情况(不规则的表面、比对象小的角等)将导致更复杂的解决方案。

利用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;
    }
}

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

在我的头顶上:

辐射4有点像:

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

门户2方式:

您很可能有一些脚本来描述您可以抓取的对象。向其中添加一个大小变量来描述对象的代理大小-比一个轴上的最大比例稍大一点。(例如,如果沙发尺寸为2x5x10,则代理为11)

禁用所持对象上的碰撞器。因此,光线投射将适用于您查看的所有其他内容


如果射线击中任何物体,则取射线点。从这一点开始,取一些大于对象大小的任意值,并将对象向您移动这么远。

据我所知,您的目标是在不同的位置生成不同的对象

我认为这里有两种方法可以结合使用

  • 您有对象自由区,并在那里随机生成对象。但是如果不能使此区域对象自由,则可能会出现问题。至少你可以用Overlapphere或其他东西检查你的区域是否空闲。如果没有,则选择另一个区域进行检查,并在该区域内的任意位置繁殖

  • 您从无法在其他对象内部繁殖的高度“放置”对象。然后,你们可以让物体落下或在障碍物前垂直追踪位置,并在此时繁殖


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

    要使用它,请检查文档页面上的示例,查看是否有
    SweepTest
    ,复制到此处以确保完整性:

    RaycastHit hit;
    if (rb.SweepTest(transform.forward, out hit, collisionCheckDistance))
    {
        aboutToCollide = true;
        distanceToCollision = hit.distance;
    }
    
    然后使用
    transform.forward*distance to collision
    确定对象在第一次碰撞前的移动距离。例如:

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

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

    这样做可能会奏效:当放置的物体与任何物体相交时{沿光线投射交点移动它->相机原点,靠近相机。}谢谢你的回答,@31eee384。然而,我似乎不太理解它,因为它不工作,hit返回null。我只使用了您发布的第二个脚本,将其应用于我的Oculus Rift相机的中心眼锚(应该与普通相机相同)。这就是我目前所拥有的:RaycastHit;if(Game.MuebleAEditarGO.GetComponent().SweepTest(CameraFacing.transform‌​.forward,out hit,50f){Game.MuebleAEditarGO.transform.position=cameraficing.transform.forward*hit.distance;}@user2211939我已经确认它在测试项目中可以正常工作。我在更新功能中将代码放入主摄像头上的脚本中(要么
    update
    要么
    FixedUpdate
    起作用,取决于您使用它所做的操作)。也许你误解了一条错误信息:物体真的有刚体吗?(刚体也应该是运动学的,以避免当它保持在空中时向下积累速度。)我用你的解决方案编辑了这篇文章。我仍然有一些问题。不过,非常感谢:)@user2211939您说过“当RaycastHit只发现一次碰撞时”,