C# 将对象放置在光线投射点处,但在Unity3D中考虑碰撞
我正在尝试将对象放置在光线投射点的位置(光线投射发现碰撞的位置)。但我得到的是你在所附图片中看到的(两种不同的情况)。物体确实被放置在我指向的地方,但我想考虑碰撞,这样物体就不会互相穿过。 每个物体都有自己的对撞机 有人知道怎么解决这个问题吗?多谢各位 一月 编辑: 我试图实现@31eee384给出的解决方案,如下所示:C# 将对象放置在光线投射点处,但在Unity3D中考虑碰撞,c#,unity3d,collision-detection,collision,raycasting,C#,Unity3d,Collision Detection,Collision,Raycasting,我正在尝试将对象放置在光线投射点的位置(光线投射发现碰撞的位置)。但我得到的是你在所附图片中看到的(两种不同的情况)。物体确实被放置在我指向的地方,但我想考虑碰撞,这样物体就不会互相穿过。 每个物体都有自己的对撞机 有人知道怎么解决这个问题吗?多谢各位 一月 编辑: 我试图实现@31eee384给出的解决方案,如下所示: RaycastHit hit; Game.MuebleAEditarGO.transform.position = CameraFacing.transform.positi
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) 禁用所持对象上的碰撞器。因此,光线投射将适用于您查看的所有其他内容
如果射线击中任何物体,则取射线点。从这一点开始,取一些大于对象大小的任意值,并将对象向您移动这么远。据我所知,您的目标是在不同的位置生成不同的对象 我认为这里有两种方法可以结合使用
最直接的解决方案是使用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只发现一次碰撞时”,