【问题标题】:Make an object collide with certain other objects when moved to RaycastHit point in Unity3D?在Unity3D中移动到RaycastHit点时使对象与某些其他对象发生碰撞?
【发布时间】:2020-05-07 23:16:24
【问题描述】:

我正在使用鼠标指针的光线投射制作一个简单的建筑系统。要放置的对象被移动(并在单击时克隆)到射线的 RaycastHit.point,但我希望它与自己类型的对象完全碰撞,相对于命中点移动其位置。该对象可以与 gif 中所示的地形相交,但不应位于已放置的墙块内。我尝试使用 hit.distance 但无法确定检测结果,因为对象已经定位在碰撞点。我应该尝试检测位置应该如何相对于命中点移动,还是应该以某种方式让 MeshCollider 在不断移动到 RaycastHit.point 时工作?

【问题讨论】:

  • 我建议你看看Collider.bounds。它有助于了解您的网格到底有多大,因此您可以使用 extents 找到偏移量。
  • 我明白了。但是,我如何实现它们来检测将对象从命中点移动了多少? @Malphegal

标签: unity3d collision-detection collision raycasting


【解决方案1】:

这是按照您的要求做的一种方式。

private void Update()
{
    Vector3 hitPosition = Vector3.zero;
    Ray ray = _camera.ScreenPointToRay(Input.mousePosition);

    if (Physics.Raycast(ray, out RaycastHit hit))
    {
        hitPosition = hit.point; // 0
        if (hit.transform.gameObject.CompareTag("cube")) // 1
            hitPosition = ComputeHit(hit, hitPosition);
    }

    _current.transform.position = hitPosition;
}

private Vector3 ComputeHit(RaycastHit hit, Vector3 currentPosition)
{
    var bounds = hit.transform.GetComponent<MeshRenderer>().bounds; // 2

    Faces face = GetFace(hit); // 3
    switch (face)
    {
        case Faces.Up:
            currentPosition += new Vector3(0, bounds.extents.x, 0);
            break;
        case Faces.Down:
            currentPosition += new Vector3(0, -bounds.extents.x, 0);
            break;
        case Faces.East:
            currentPosition += new Vector3(bounds.extents.x, 0, 0);
            break;
        case Faces.West:
            currentPosition += new Vector3(-bounds.extents.x, 0, 0);
            break;
        case Faces.North:
            currentPosition += new Vector3(0, 0, bounds.extents.x);
            break;
        case Faces.South:
            currentPosition += new Vector3(0, 0, -bounds.extents.x);
            break;
    }

    return currentPosition;
}

public Faces GetFace(RaycastHit hit)
{
    Vector3 res = hit.normal - Vector3.up;

    if (res == new Vector3(0, -1, -1))
        return Faces.South;

    if (res == new Vector3(0, -1, 1))
        return Faces.North;

    if (res == new Vector3(0, 0, 0))
        return Faces.Up;

    if (res == new Vector3(1, 1, 1))
        return Faces.Down;

    if (res == new Vector3(-1, -1, 0))
        return Faces.West;

    if (res == new Vector3(1, -1, 0))
        return Faces.East;

    return Faces.Nothing;
}

public enum Faces
{
    Nothing,

    Up,
    Down,
    East,
    West,
    North,
    South
}

我会进一步解释:

在您的更新方法中,一旦您检测到hit.point 位置// 0 的位置,您就可以检查您是否瞄准了一个立方体// 1。我不知道你在实例化后如何管理它们,但我添加了一个名为cube 的标签。 它可以是任何名称或图层。 也可以是一个组件,用hit.transform.GetComponent&lt;...&gt;()方法检查这个组件是否存在。

然后,您获得目标立方体边界// 2 并使用法线确定您瞄准的方向// 3

从这里开始,取决于目标面(6 个中的一个),您在 3 个轴之一上为 hit.point 添加偏移量。

bounds.extents 给你一半的脸,使用bounds.extents.xbounds.extents.ybounds.extents.z。 您只希望偏移量为面的一半长度,因为当您用鼠标移动立方体时,立方体的位置在它的中心。

这是一个例子:

【讨论】:

  • 我花了一些时间来整合,但它就像一个魅力。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-20
  • 1970-01-01
  • 2021-04-18
  • 2012-05-24
  • 1970-01-01
  • 2015-04-03
  • 1970-01-01
相关资源
最近更新 更多