当移动到Unity3D中的RaycastHit点时,使一个对象与某些其他对象发生碰撞? [英] Make an object collide with certain other objects when moved to RaycastHit point in Unity3D?

查看:75
本文介绍了当移动到Unity3D中的RaycastHit点时,使一个对象与某些其他对象发生碰撞?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

这是完成您所要询问的一种方法.

 私有无效Update(){Vector3 hitPosition = Vector3.zero;Ray ray = _camera.ScreenPointToRay(Input.mousePosition);如果(Physics.Raycast(ray,out RaycastHit hit)){hitPosition = hit.point;//0如果(hit.transform.gameObject.CompareTag("cube"))//1hitPosition = ComputeHit(hit,hitPosition);}_current.transform.position = hitPosition;}私有Vector3 ComputeHit(RaycastHit hit,Vector3 currentPosition){var bounds = hit.transform.GetComponent< MeshRenderer>().bounds;//2Faces face = GetFace(hit);//3开关(正面){Case Faces.Up:currentPosition + = new Vector3(0,bounds.extents.x,0);休息;Case Faces.Down:currentPosition + = new Vector3(0,-bounds.extents.x,0);休息;案例Faces.East:currentPosition + =新的Vector3(bounds.extents.x,0,0);休息;Case Faces.West:currentPosition + =新的Vector3(-bounds.extents.x,0,0);休息;案例Faces.North:currentPosition + = new Vector3(0,0,bounds.extents.x);休息;案例Faces.South:currentPosition + = new Vector3(0,0,-bounds.extents.x);休息;}返回currentPosition;}公众面孔GetFace(RaycastHit hit){Vector3 res = hit.normal-Vector3.up;如果(res == new Vector3(0,-1,-1))返回Faces.South;如果(res == new Vector3(0,-1,1))返回Faces.North;如果(res == new Vector3(0,0,0))返回Faces.Up;如果(res == new Vector3(1,1,1))返回Faces.Down;如果(res == new Vector3(-1,-1,0))返回Faces.West;如果(res == new Vector3(1,-1,0))返回Faces.East;返回Faces.Nothing;}公共枚举面孔{没有什么,向上,下,东方的,西,北,南} 

我将进一步解释:

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

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

从此处开始,根据目标面部(6个中的一个),在3个轴之一上向 hit.point 添加偏移量.

I'm making a simple building system using Raycasting from the mouse pointer. The object that is to be placed is moved (and cloned on click) to the RaycastHit.point of the ray, but I want it to fully collide with objects of its own type, shifting its position relative to the hit point. The object can intersect the terrain as shown in the gif, but should not be inside of the already placed wall blocks. I tried using hit.distance but couldn't figure the detection out, since the object is being positioned at the collision point already. Should I try and detect how should the position should shift relative to the hit point or should I somehow make the MeshCollider work while it's being constantly moved to the RaycastHit.point?

解决方案

This is one way to do what you ask.

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
}

I will explain further :

In your Update method, once you detect where is the hit.point location // 0, you can check whether or not you aim a cube or not // 1. I don't know how you manage them once instantiated, but I add a tag named cube. It could be any name or a layer. It could also be a component and check whether or not this component exist with hit.transform.GetComponent<...>() method.

Then, you get the aimed cube bounds // 2 and use the normal to determine which direction you are aiming // 3.

From here, depends on the aimed face (one out of 6), you add an offset to your hit.point on one of the 3 axes.

bounds.extents give you the half of the faces, using bounds.extents.x, bounds.extents.y and bounds.extents.z. You only want the offset to be half length of the face, because when you move your cube with the mouse, the location of the cube is in the center of it.

Here is an example :

这篇关于当移动到Unity3D中的RaycastHit点时,使一个对象与某些其他对象发生碰撞?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆