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
相关产品推荐
相关产品推荐

