You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中使用Physics.OverlapSphere时如何避免检测自身?

3D塔防游戏路径生成问题解决

问题描述

我正在开发一款3D塔防游戏,场景内有用于路径生成的10×10网格Tile。需要实现点击Tile时检测周围Tile,以此避免生成非法路径,但当前使用Physics.OverlapSphere时会检测到Tile自身,且无法通过分层解决该问题(所有Tile都需检测直路径状态),同时要防止出现相邻直路径的情况。

现有代码

PathCreator.cs

using System.Collections;
using System.Collections.Generic;
using Unity.Android.Types;
using UnityEngine;

public class PathCreator : MonoBehaviour
{
    public Mesh StraightPath;
    public Mesh TurnPath;
    public float radius = 5f;
    public static string targetTag = "StraightPath";
    public static bool Message = false;
    public static bool Message2 = false;
    public int pathLayer;
    public Collider myCollider;
    // Start is called before the first frame update
    void Start()
    {
        pathLayer = 7 << LayerMask.NameToLayer("Tile");
        myCollider = GetComponent<Collider>();
    }

    // Update is called once per frame
    void Update()
    {
        Collider[] hitColliders = Physics.OverlapSphere(transform.position, radius, pathLayer);
        foreach (var hitCollider in hitColliders)
        {
            if (hitCollider != myCollider)
            {
                if (hitCollider.gameObject.CompareTag(targetTag))
                {

                    if (!Message2)
                    {
                        Message2 = true;
                        print("Found Me!");
                    }
                }
            }
            else
            {
                if (!Message)
                {
                    print("Found path!");
                    Message = true;
                }
            }
        }
    }
    private void OnMouseDown()
    {
        print("click!");
        gameObject.GetComponent<MeshFilter>().mesh = StraightPath;
        gameObject.tag = "StraightPath";
        Message = false;
        Message2 = false;
    }
}

PathSelect.cs(暂未使用)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PathSelect : MonoBehaviour
{
    public GameObject StraightPath;
    public GameObject TurnPath;
    public Camera PathChooser;
    public Camera MainCamera;
    // Start is called before the first frame update
    void Start()
    {
        PathChooser.enabled = true;
        MainCamera.enabled = false;
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

解决方案

1. 修正LayerMask赋值错误

当前pathLayer = 7 << LayerMask.NameToLayer("Tile");是错误的,LayerMask通过位掩码表示单个层,正确写法为:

void Start()
{
    int tileLayerIndex = LayerMask.NameToLayer("Tile");
    pathLayer = 1 << tileLayerIndex;
    myCollider = GetComponent<Collider>();
}

2. 点击时定向检测相邻直路径

将检测逻辑从Update移到OnMouseDown中,仅在点击时判断是否允许放置直路径,通过网格方向精准检测相邻Tile,避免OverlapSphere误检自身的问题:

修改PathCreator.cs中的OnMouseDown方法,并新增检测方法:

private void OnMouseDown()
{
    print("click!");
    // 先检查相邻Tile是否存在直路径
    if (!HasAdjacentStraightPath())
    {
        gameObject.GetComponent<MeshFilter>().mesh = StraightPath;
        gameObject.tag = "StraightPath";
        print("直路径放置成功");
    }
    else
    {
        print("相邻Tile已有直路径,无法放置");
    }
    Message = false;
    Message2 = false;
}

private bool HasAdjacentStraightPath()
{
    // 根据你的Tile网格间距调整此值,比如每个Tile中心间隔1单位就设为1f
    float tileSpacing = 1f;
    // 定义四个相邻方向(根据场景坐标系调整,比如Z轴为前后,X轴为左右)
    Vector3[] adjacentPositions = new Vector3[]
    {
        transform.position + Vector3.forward * tileSpacing,
        transform.position + Vector3.back * tileSpacing,
        transform.position + Vector3.left * tileSpacing,
        transform.position + Vector3.right * tileSpacing
    };

    foreach (Vector3 pos in adjacentPositions)
    {
        // 检测对应位置的Tile Collider
        Collider[] colliders = Physics.OverlapPoint(pos, pathLayer);
        foreach (Collider col in colliders)
        {
            if (col.CompareTag(targetTag))
            {
                return true;
            }
        }
    }
    return false;
}

3. 彻底排除自身检测(可选)

如果仍需使用OverlapSphere,可以在遍历结果时直接跳过自身GameObject:

foreach (var hitCollider in hitColliders)
{
    if (hitCollider.gameObject == gameObject)
        continue; // 跳过自身

    if (hitCollider.CompareTag(targetTag))
    {
        // 处理相邻直路径逻辑
    }
}

内容的提问来源于stack exchange,提问作者Coco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:00:08