Unity中DFS查找回合制Tile游戏可移动区域时触发空引用异常
空引用异常排查与解决
问题原因
错误触发在FindNeighbouringTiles方法的射线检测链式调用处(对应报错行UnitManager.cs:103)。当向网格边缘外的方向发射射线时,射线未命中任何Collider,此时Physics2D.Raycast(...)返回的RaycastHit2D对象的collider属性为null,直接链式访问.collider.gameObject.GetComponent<Tile>()就会触发空引用异常。
比如起始Tile位于(1,1)时,若某个方向超出16×9的网格范围,射线找不到对应Tile的Collider,就会触发该错误。
解决方法
1. 修复射线检测的空引用问题
拆分射线检测的调用步骤,先判断是否命中Collider,再获取Tile组件,同时优化射线检测逻辑:
public List<Tile> FindNeighbouringTiles(Tile origin) { List<Tile> neighbouringTiles = new List<Tile>(); // 假设所有Tile都放在名为"Tile"的图层,通过LayerMask过滤仅检测Tile int tileLayerMask = LayerMask.GetMask("Tile"); // 射线检测距离设为1(假设Tile之间的间距为1单位) float rayDistance = 1f; // 向上检测相邻Tile RaycastHit2D upHit = Physics2D.Raycast(origin.transform.position, Vector2.up, rayDistance, tileLayerMask); if (upHit.collider != null) { Tile upTile = upHit.collider.GetComponent<Tile>(); if (upTile != null) neighbouringTiles.Add(upTile); } // 向下检测相邻Tile RaycastHit2D downHit = Physics2D.Raycast(origin.transform.position, Vector2.down, rayDistance, tileLayerMask); if (downHit.collider != null) { Tile downTile = downHit.collider.GetComponent<Tile>(); if (downTile != null) neighbouringTiles.Add(downTile); } // 向左检测相邻Tile RaycastHit2D leftHit = Physics2D.Raycast(origin.transform.position, Vector2.left, rayDistance, tileLayerMask); if (leftHit.collider != null) { Tile leftTile = leftHit.collider.GetComponent<Tile>(); if (leftTile != null) neighbouringTiles.Add(leftTile); } // 向右检测相邻Tile RaycastHit2D rightHit = Physics2D.Raycast(origin.transform.position, Vector2.right, rayDistance, tileLayerMask); if (rightHit.collider != null) { Tile rightTile = rightHit.collider.GetComponent<Tile>(); if (rightTile != null) neighbouringTiles.Add(rightTile); } return neighbouringTiles; }
- 添加射线距离参数,避免射线无限制穿透;
- 使用
LayerMask仅检测Tile图层,无需临时禁用自身Collider,减少潜在逻辑问题; - 分步判断
collider和Tile组件是否为空,彻底规避空引用。
2. 优化DFS遍历性能(可选)
原代码中visited使用List<Tile>,Contains方法为O(n)时间复杂度,网格较大时遍历效率低下。建议替换为HashSet<Tile>:
HashSet<Tile> visited = new HashSet<Tile>(); // 替换原List<Tile>
HashSet的Contains和Add操作均为O(1),能显著提升DFS的遍历速度。
3. 后续移动步数限制实现建议
当需要添加移动步数限制时,可在DFS过程中记录每个Tile的步数(从起点到该Tile的距离),当步数超过限制时停止遍历。可以通过字典存储每个Tile对应的步数,或者在Tile类中临时添加步数字段。
内容的提问来源于stack exchange,提问作者HGBadger
相关产品推荐
相关产品推荐

