【问题标题】:Multiple raycasts and only two are working多个光线投射,只有两个在工作
【发布时间】:2019-02-24 17:42:06
【问题描述】:

我正在开发一个 AI,我想给它提供玩家(汽车)与游戏中(几乎)所有其他东西(墙壁、街道中间、其他汽车)之间的距离。我正在使用 Physics.Raycast。问题是只有 DistanceToRightSideOfMOTS (MOTS: middle of the street) 和 DistanceToBackWall 有效。这是我的代码:

private void FixedUpdate()
{
    RequestDecision();
    RequestAction();

     // Get the distances to the walls

    // Get distance to left wall
    RaycastHit hit;
    if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.left), out hit, 25, 1 << 11))
    {
        DistanceToLeftWall = hit.distance / 25;
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.left) * hit.distance, Color.red);
    }
    else
    {
        DistanceToLeftWall = 1;
    }

    // Get distance to right wall
    if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.right), out hit, 25, 1 << 12))
    {
        DistanceToRightWall = hit.distance / 25;
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.right) * hit.distance, Color.red);
    }
    else
    {
        DistanceToRightWall = 1;
    }

    // Get distance to front wall (it sees 2x farther because it's hard to turn on the corner)
    if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, 50, (1 << 11) | (1 << 12)))
    {
        DistanceToFrontWall = hit.distance / 50;
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.red);
    }
    else
    {
        DistanceToFrontWall = 1;
    }
    // Get distance to back wall
    if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.back), out hit, 50, (1 << 11) | (1 << 12)))
    {
        DistanceToBackWall = hit.distance / 50;
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.back) * hit.distance, Color.red);
    }
    else
    {
        DistanceToBackWall = 1;
    }

    //////////////////

    // Get the distance to other cars

    /////////////////

    // Get distance to left car
    if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.left), out hit, 25, 1 << 13))
    {
        DistanceToLeftCar = hit.distance / 25;
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.left) * hit.distance, Color.green);
    }
    else
    {
        DistanceToLeftCar = 1;
    }

    // Get distance to right car
    if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.right), out hit, 25, 1 << 13))
    {
        DistanceToRightCar = hit.distance / 25;
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.right) * hit.distance, Color.green);
    }
    else
    {
        DistanceToRightCar = 1;
    }

    // Get distance to front car
    if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, 50, 1 << 13))
    {
        DistanceToFrontCar = hit.distance / 50; // We divide the distance to normalize the input
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.green);
    }
    else
    {
        DistanceToFrontCar = 1;
    }
    // Get distance to back car
    if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.back), out hit, 50, 1 << 13))
    {
        DistanceToBackCar = hit.distance / 50;
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.back) * hit.distance, Color.green);
    }
    else
    {
        DistanceToBackCar = 1;
    }


    //Get distances to the middle of the street


    //Get distance from the left side
    if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.left), out hit, 10, 1 << 14))
    {
        DistanceToLeftSideOfMOTS = hit.distance / 10;
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.left) * hit.distance, Color.blue);
    }
    else
    {
        DistanceToLeftSideOfMOTS = 1;
    }
    //Get distance from the right side
    if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.right), out hit, 10, 1 << 14))
    {
        DistanceToRightSideOfMOTS = hit.distance / 10;
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.right) * hit.distance, Color.blue);
    }
    else
    {
        DistanceToRightSideOfMOTS = 1;
    }

}

其他距离总是返回 1,即使它不应该。为什么不起作用,我该如何解决?

Edit1:我不知道为什么,但是当我将汽车超靠近右墙时,DistanceToRightWall 开始工作,而 DistanceToBackCar 仅在我离汽车至少 15m 时才有效。有没有其他选择?

Edit2:我在墙壁和街道中间使用了平面。当我查看物理调试可视化时,我从一侧看到了平面对撞机,但从另一侧看不到。我是 Unity 新手,所以也许这可能是问题所在。

Edit3:我在街道中间添加了一个盒子碰撞器,DistanceToLeftSideOfMOTS 开始工作,但我尝试用墙壁来做,但没有成功。

Edit4:我把盒子对撞机做得更大,而且效果很好。现在唯一的问题是汽车。

【问题讨论】:

  • 请注意,您对不同的 Physics.Raycast 调用使用不同的图层蒙版。这可能与您的问题有关吗?
  • @elgonzo 我认为这不是问题,因为 DistanceToRightSideOfMOTS 有效,而 DistanceToLeftSideOfMOTS 无效,即使它们都使用相同的图层蒙版:(
  • 只是一个提示:我更喜欢使用一些LayerMask 字段来配置光线的图层,例如public LayerMask WallLayers;。你可以简单地在检查器中选择相应的层并像Physics.Raycast(transform.position, transform.TransformDirection(Vector3.left), out hit, 25, WallLayers) 一样使用它

标签: c# unity3d artificial-intelligence


【解决方案1】:

我构建了一个示例场景来试用您的代码,但找不到任何问题。确保您的汽车对象方向正确,并且墙壁和汽车具有适当的图层和分配给它们的碰撞器。 Unity 的Physics Debug Visualization 可能会有所帮助。

另外,最好多保留一点DRY。例如,您可以将所有 raycast 调用移动到一个方法中以减少重复。这样一来,如果出现问题,可以查看的地方就更少了:

private void FixedUpdate()
{
    RequestDecision();
    RequestAction();
    UpdateWallDistances();
}

private void UpdateWallDistances()
{
    int leftWallMask = 1 << 11;
    int rightWallMask = 1 << 12;
    int wallMask = leftWallMask | rightWallMask;
    int carMask = 1 << 13;
    int middleOfStreetMask = 1 << 14;

    // Get the distances to the walls
    DistanceToLeftWall = GetDistance(Vector3.left, 25, leftWallMask, Color.red);
    DistanceToRightWall = GetDistance(Vector3.right, 25, rightWallMask, Color.red);
    DistanceToFrontWall = GetDistance(Vector3.forward, 50, wallMask, Color.red);
    DistanceToBackWall = GetDistance(Vector3.back, 50, wallMask, Color.red);

    // Get the distance to other cars
    DistanceToLeftCar = GetDistance(Vector3.left, 25, carMask, Color.green);
    DistanceToRightCar = GetDistance(Vector3.right, 25, carMask, Color.green);
    DistanceToFrontCar = GetDistance(Vector3.forward, 50, carMask, Color.green);
    DistanceToBackCar = GetDistance(Vector3.back, 50, carMask, Color.green);

    //Get distances to the middle of the street
    DistanceToLeftSideOfMOTS = GetDistance(Vector3.left, 10, middleOfStreetMask, Color.blue);
    DistanceToRightSideOfMOTS = GetDistance(Vector3.right, 10, middleOfStreetMask, Color.blue);
}

private float GetDistance(Vector3 direction, float maxDistance, int layerMask, Color debugColor)
{
    RaycastHit hit;
    if (Physics.Raycast(transform.position, transform.TransformDirection(direction), out hit, maxDistance, layerMask))
    {
        Debug.DrawRay(transform.position, transform.TransformDirection(direction) * hit.distance, debugColor);
        return hit.distance / maxDistance;
    }
    else
    {
        return 1;
    }
}

【讨论】:

  • 我试过你的代码,但它和我的一样。我不认为我的对撞机和图层蒙版是问题,因为 DistanceToBackWall 有效,但即使它们具有相同的图层蒙版,DistanceToFrontWall 也不起作用(并且它们应该与相同的东西发生碰撞)。但是,我将飞机用于墙壁和街道中间。当我查看物理调试可视化时,我从一侧看到了平面对撞机,但从另一侧看不到。我是统一的新手,所以你认为这可能是问题吗?
  • 另外,“确保您的汽车对象方向正确”是什么意思。
  • 我的意思是,您必须确保脚本附加到的对象的方向是这样的,即光线投射从一个位置开始,并且朝着您希望它们去的方向。您可以添加额外的调试行来可视化光线投射的方向。是的,飞机的网格对撞机只会被来自一侧的光线投射击中。如果您希望物体从任何一侧被击中,您可以添加一个盒子对撞机。
  • 谢谢,我的问题出在对撞机上,物理调试可视化对我很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 2016-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多