/// <summary> /// 检测玩家是否在机器人的球形碰撞体内,这个碰撞体是机器人的侦测范围,玩家在内部会进行视野检测和声音检测 /// </summary> private void OnTriggerStay(Collider other) { //视野检测 //玩家在碰撞体中且玩家在机器人视角的扇形范围内则机器人发现了玩家 if(other.tag == Tags.player && Vector3.Angle(transform.forward,other.transform.position - transform.position) <= (fieldOfView * 0.5f)) { playerInSight = true; //调用GameManager脚本的SeePlayer方法触发警报 GameManager._instance.SeePlayer(other.transform); print(count + ":" + "if"); return; } else { playerInSight = false; print(count + ":" + "else"); } count++; }
使用计数器count记录进入OntriggerStay方法的次数,在其中有一段if和else代码,执行了这段代码就会打印计数和if/else,实际执行的结果
可以看到,在同样的情况下,偶尔进入if代码块,大部分情况下进入else代码块,甚至第1260次同时进入if和else代码块(这怎么可能呢?)
解决:将if的两个同时成立的条件分两次判定
private void OnTriggerStay(Collider other) { //视野检测 //玩家在碰撞体中且玩家在机器人视角的扇形范围内则机器人发现了玩家 if(other.tag == Tags.player) { if(Vector3.Angle(transform.forward, other.transform.position - transform.position) <= (fieldOfView * 0.5f)) { playerInSight = true; //调用GameManager脚本的SeePlayer方法触发警报 GameManager._instance.SeePlayer(other.transform); print(count + ":" + "if"); return; } else { playerInSight = false; print(count + ":" + "else"); } count++; } }
执行结果:
结果完全没有问题,bug原因是else代码写错了地方,修改前后的判断过程完全不一样,但是if和else同时执行的问题到底是怎么回事呢?
解答:想清楚了,因为我添加了return方法,所以执行完if代码块后count++没来得及执行就直接返回了,导致if执行后下一次的else的count和这一次相同。
细节梳理:这里的ontriggerstay用来检测机器人是否看见了玩家,所以trigger碰撞器的范围就是机器人的视野范围,因此trigger碰撞器较大,因此同一时刻内碰撞器内有多个非玩家碰撞体。按照原来的代码执行,每一个碰撞体都会进行一次判断,但是标签不是player,因此即使玩家在视野范围内满足条件,也只会触发一次if,而其他碰撞体都会触发else,导致if中playerinsight瞬间被修改为true后又被修改为false,呈现出来的效果就是这个值好像一直为false,无法达到检测的效果。
总结:进行有if有else的判断的时候一个if可以少判断几个条件,分多次判断,不然容易出现问题,这里修改前后的else意义就不一样,但是开始写的时候没有察觉。