Unity中友方AI选择新目标时随机停止移动问题求助
问题分析与解决办法
核心原因
你的友方AI随机停止移动的问题,根源在于目标引用失效未被及时检测和选目标时可能选中已销毁/待销毁的敌人:
- 敌人被摧毁时,
currentTarget指向的Transform会延迟到帧末才变为null,此之前Update里的currentTarget != null判断仍为true,AI试图向不存在的目标移动,表现为停止; FindGameObjectsWithTag("Enemy")可能返回已标记销毁但未完成清理的敌人,选中这类目标后,下一帧引用会直接失效,AI失去目标停止;- 若AI攻击濒死敌人,造成伤害后敌人立即销毁,但
FindNewTarget刚好选中这个即将消失的敌人,会触发后续目标失效。
解决步骤
1. 实时校验目标有效性
在Update中增加目标对象的有效性检查,确保AI不会向无效目标移动,且失效时立即重新找目标:
private void Update() { // 校验目标是否存在且活跃 if (currentTarget != null && currentTarget.gameObject != null && currentTarget.gameObject.activeInHierarchy) { Vector2 direction = currentTarget.position - transform.position; Vector2 newPosition = Vector2.MoveTowards(transform.position, currentTarget.position, moveSpeed * Time.deltaTime); transform.position = newPosition; } // 目标失效时自动重新寻找 else { FindNewTarget(); } }
2. 筛选活跃敌人再选目标
修改FindInitialTarget和FindNewTarget,只从活跃的敌人中筛选目标,避免选中已销毁对象:
private void FindInitialTarget() { GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy"); List<GameObject> activeEnemies = new List<GameObject>(); // 过滤出存在且活跃的敌人 foreach (GameObject enemy in enemies) { if (enemy != null && enemy.activeInHierarchy) { activeEnemies.Add(enemy); } } if (activeEnemies.Count > 0) { float closestDistance = Mathf.Infinity; foreach (GameObject enemy in activeEnemies) { float distance = Vector3.Distance(transform.position, enemy.transform.position); if (distance < closestDistance) { closestDistance = distance; currentTarget = enemy.transform; } } } else { currentTarget = null; } } private void FindNewTarget() { GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy"); List<GameObject> activeEnemies = new List<GameObject>(); foreach (GameObject enemy in enemies) { if (enemy != null && enemy.activeInHierarchy) { activeEnemies.Add(enemy); } } if (activeEnemies.Count > 0) { int randomIndex = Random.Range(0, activeEnemies.Count); currentTarget = activeEnemies[randomIndex].transform; Debug.Log("New Target Chosen"); } else { currentTarget = null; } }
3. 敌人死亡时主动通知AI更新(可选)
在敌人的HealthDamage脚本中,当敌人死亡时主动通知持有自身为目标的AI更新,避免无效引用残留:
public void TakeDamage(int damage) { currentHealth -= damage; if (currentHealth <= 0) { // 通知所有以当前敌人为目标的AI更换目标 FriendlyAI[] friendlyAIs = FindObjectsOfType<FriendlyAI>(); foreach (FriendlyAI ai in friendlyAIs) { if (ai.currentTarget == transform) { ai.FindNewTarget(); } } Destroy(gameObject); } }
额外建议
- 避免频繁调用
FindGameObjectsWithTag,可通过对象池或事件系统维护敌人列表,提升性能; - 无目标时可添加待机逻辑(如原地巡逻),让AI行为更自然。
内容的提问来源于stack exchange,提问作者Carson
相关产品推荐
相关产品推荐

