首页 > 解决方案 > 在Unity3D中移动到RaycastHit点时使对象与某些其他对象发生碰撞?

问题描述

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

替代文字

标签: unity3dcollision-detectioncollisionraycasting

解决方案


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

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
}

我将进一步解释:

在您的 Update 方法中,一旦您检测到hit.point位置在哪里// 0,您就可以检查您是否瞄准了立方体// 1。我不知道实例化后如何管理它们,但我添加了一个名为cube. 它可以是任何名称或图层。它也可以是一个组件,并通过hit.transform.GetComponent<...>()方法检查该组件是否存在。

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

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

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

这是一个例子:

立方体示例


推荐阅读