Unity敌怪靠近玩家时丢失视野进入Idle状态问题求助
问题修复方案
- 核心问题1:
hasSeenPlayer参数为值传递,C#中值类型参数默认按值传递,函数内对该参数的修改仅作用于副本,不会同步到外部的HasSeenPLayer变量,导致if (distDif <= inRange && hasSeenPlayer)分支永远无法触发,因此不会输出I saw the player again日志,也不会自动转向玩家锁定视野。 - 核心问题2:当前逻辑要求无论距离多近都需要满足视野角度条件才会返回
true,当敌怪靠近玩家时若未及时转向,视野角度判断不通过,函数返回false就会触发Idle状态切换。
修复代码
首先修改PlayerPos类的FindPlayerPos方法,将hasSeenPlayer改为引用传递,同时优化近距离逻辑:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerPos : MonoBehaviour { // hasSeenPlayer参数增加ref关键字,改为引用传递 public static bool FindPlayerPos(float inRange, GameObject playerPos, float inView, GameObject self, ref bool hasSeenPlayer) { float distDif = Vector3.Distance(playerPos.transform.position, self.transform.position); // 已经见过玩家且在攻击范围内,直接判定发现玩家,不需要卡视野限制 if (distDif <= inRange && hasSeenPlayer) { self.transform.LookAt(playerPos.transform.position); Debug.Log("I saw the player again"); return true; } // 第一次发现玩家的逻辑,需要同时满足距离、视野条件 if (distDif <= inRange && PlayerIsInSight(inView, playerPos, self) && !hasSeenPlayer) { hasSeenPlayer = true; Debug.Log("I see player"); return hasSeenPlayer; } // 不满足条件则判定丢失玩家,重置标记 hasSeenPlayer = false; Debug.Log("I dont see player"); return false; } public static bool PlayerIsInSight(float inView, GameObject playerPos, GameObject self) { Vector3 targetDir = playerPos.transform.position - self.transform.position; Vector3 forward = self.transform.forward; float angle = Vector3.SignedAngle(targetDir, forward, Vector3.up); float selfHeight = self.GetComponent<Collider>().bounds.size.y; if (angle <= inView && angle >= -inView && playerPos.transform.position.y <= self.transform.position.y + selfHeight/2 + selfHeight && playerPos.transform.position.y >= (self.transform.position.y - selfHeight) - selfHeight / 2) { return true; } return false; } }
然后修改调用处代码,增加ref关键字匹配参数要求:
if (!PlayerPos.FindPlayerPos(AttackRange, playerPos, inView, self, ref HasSeenPLayer)) { // 原有切换Idle状态的逻辑 }
内容的提问来源于stack exchange,提问作者Arnice123
相关产品推荐
相关产品推荐

