带有 LayerMask 的 Unity Physics.Raycast 不会检测图层上的对象。使用了位移,尝试了反相层,仍然没有任何效果
Posted
技术标签:
【中文标题】带有 LayerMask 的 Unity Physics.Raycast 不会检测图层上的对象。使用了位移,尝试了反相层,仍然没有任何效果【英文标题】:Unity Physics.Raycast with LayerMask does not detect object on layer. Used bitshifting, tried inverting layer, still nothing works 【发布时间】:2021-10-05 21:05:37 【问题描述】:这里是 Unity 中级开发人员的新手。在过去的 ~2 天里,我遇到了一个非常重要的障碍,涉及对具有特定图层的对象的光线投射检测。我一直在研究这个问题很多,我发现的所有解决方案似乎都没有反映我面临的奇怪问题。
基本上,问题遵循以下事件序列:
-
我的玩家角色有一个名为“InSightBox”的视觉锥形触发网格,它检测所有带有“Mob”标签的对象并将它们添加到名为“MobsInRange”的对撞机列表中。
public List<Collider> mobsInRange;
public List<Collider> GetColliders()
return mobsInRange;
// Start is called before the first frame update
void Start()
mobsInRange = new List<Collider>();
// Update is called once per frame
void Update()
//add enemy with tag 'mob' to list
private void OnTriggerEnter(Collider other)
if(!mobsInRange.Contains(other) && other.tag == "Mob")
mobsInRange.Add(other);
//remove enemy with tag 'mob' to list
private void OnTriggerExit(Collider other)
if (mobsInRange.Contains(other) && other.tag == "Mob")
mobsInRange.Remove(other);
-
然后,此列表被馈送到包含与玩家相关的所有内容的根/父玩家游戏对象。
public Transform closestMob;
public List<Collider> mobs;
public Transform GetClosestEnemy()
Transform tMin = null;
float minDist = Mathf.Infinity;
Vector3 currentPos = transform.position;
foreach(Collider trans in mobs)
//find enemy with closest distance and set tMin to it. Method returns tMin
float dist = Vector3.Distance(trans.transform.position, currentPos);
if(dist < minDist)
tMin = trans.transform;
minDist = dist;
//Debug.Log(tMin);
return tMin;
-
然后玩家使用“查看”方法来查找所有“生物”中离玩家最近的。玩家将设置他们的正向变换以查看最近的生物。
问题步骤---> 4)当玩家举起枪并试图射击最近的敌人时,会投射一条带有图层蒙版的射线,该图层仅查找“敌人”图层上的对象,第 8 层。当射线检测到敌人时,敌人脚本应该触发其“TakeDamage”方法,该方法将“curHealth”变量减少 8。唯一的问题是,演员似乎没有检测到“敌人”层上的敌人对象。
LayerMask layerMask = 1 << 8;
void Fire()
//play the audio of the gunshot
StartCoroutine("SetPlaying");
RaycastHit hit;
//cast a ray from the player forward and check if the hit object is on layer 'Enemy'
if (Physics.Raycast(transform.position, transform.forward, out hit, Mathf.Infinity, layerMask))
//if hit object is an enemy, set its 'gotShot' bool to true
print("hit enemy");
closestMob.GetComponent<EnemyBase>().gotShot = true;
//play gunshot sound and stop player from turning
source.clip = fireSound;
source.PlayOneShot(fireSound, gunshotVolumeScale);
turnSpeed = 0;
我还要注意,我看到的所有解决此问题的方法都不适合我。我声明了一个名为“layerMask”的 int 变量,并在 Awake() 中通过将第 8 层移位到其中来初始化它(即 int layerMask = 1 奇怪的地方(至少据我所知),当我在演员表中反转掩码(~layerMask)时,它完全符合我的预期,并开始在当玩家“射击”任何没有“敌人”层的东西时,光线投射 if 语句。
当我快要把脸撞到桌子上时,任何帮助都将不胜感激:/
旁注:我已经到了可以将“射程”立方体触发器附加到我的播放器并在触发 Fire() 事件时启用它的地步,然后拥有它检查带有“mob”标签的游戏对象,因为这种检测对我来说最有效。
【问题讨论】:
很确定你需要~那个图层蒙版或者你排除了你唯一想要的东西 不。当我反转它时,它会按预期工作,并在遇到任何不在“敌人”层中的东西时触发代码。问题是当我切换回来时,敌人层中的对象没有被检测到。奇怪的是,文档中的说法与所有人所说的相反。 【参考方案1】:首先,请确保您没有将图层与标签混淆。它们是不同的。
其次,摆脱任何隐式操作和引用,即不要使用位移、层索引或任何非直接引用。相反,创建这样的东西:
[SerializedField] private LayerMask _layerMask;
使用检查器分配所需的层。
这样您将明确看到您正在使用哪个层。这不仅对您有用,而且对您将来忘记图层索引时也有用。此外,对于不熟悉该项目的任何人。
第三个是调试。确保您的光线投射在其他方面按预期工作:
尝试删除layerMask
并查看光线是否到达您想要的位置
使用自定义 Gizmo 检查您是否将光线投射到正确的方向
尝试使用RaycastAll
。也许有些物体比你想象的更早捕捉(阻挡)你的光线
【讨论】:
是的,它肯定不是标签。标签是“Mob”,我用它来添加列表。这是我在 raycast 字段下指定的 100% 层。移除图层蒙版正如您所期望的那样,并开始在所有内容上触发演员阵容中的代码。此外,当使用 Debug.Ray 时,它确实会投射到指定为敌人的对象。 等等,你关于使用 Raycast 的第三条建议都奏效了!!!看起来正在发生的事情是包含脚本的“敌人”对象包含在光线投射命中时包含在另一个也有对撞机的 Empty 中。我意识到把它作为一个空的孩子是相当多余的,所以我将敌人的预制件重建为一个单独的对象,现在它可以很好地工作,即使只是 Raycast 而不是 RaycastAll。谢谢 JottoWorol !!!!!!【参考方案2】:看起来问题在于我的“敌人”预制件包含嵌套在空游戏对象中的必要组件(刚体、碰撞器、脚本、导航网格代理)。起初我想把一些东西做成一个预制件,你需要把它放在一个空的里面。我现在看到这是相当多余且没有必要的(至少在我的情况下)。
Physics.RaycastAll 解决了这个问题,因为它不再被父空的对撞机“停止”并且也击中了子。
实际上,我只是使用常规 Physics.Raycast 通过将 Enemy 预制件重建为单个 Capsule 对象(稍后我将用角色网格替换)来让它工作。
旁注 在我开始使用这种新方法之前,我还使用了另一种以非常轻量级的方式实现相同目标的方法。
-
我在播放器前面添加了一个细长的盒子触发器,以便它有足够的距离与射击范围内的任何敌人发生碰撞。
然后,只要玩家进入“瞄准”状态,我就会启用触发器。如果触发器与任何带有“Mob”标签的网格碰撞,它会在玩家身上设置一个布尔值,指示敌人是否在范围内。
然后,如果敌人在射程内并且玩家进入“开枪”状态,则会触发 Enemy Base 脚本中的一个方法,通过一个名为damagetaken 的公开决定的变量来减少敌人的生命值。
Raycast 方法和 box trigger 方法对我来说同样适用,但 box trigger 只需花费更少的时间来弄清楚并且让我不那么头疼哈哈。
希望这可以帮助其他处于困境的人!!!!!!
【讨论】:
以上是关于带有 LayerMask 的 Unity Physics.Raycast 不会检测图层上的对象。使用了位移,尝试了反相层,仍然没有任何效果的主要内容,如果未能解决你的问题,请参考以下文章