Unity跨场景生成角色失败求助:NavMesh未加载导致代理创建失败
解决方案
核心问题定位
当前问题出在LoadSceneAsync是异步加载逻辑,你调用OnLevelSelect事件时新场景的NavMesh还未生成完成,此时生成带NavMeshAgent的角色就会触发"Failed to create agent because there is no valid NavMesh"错误。同时你的RandomNavMeshLocation方法未校验随机点是否在NavMesh范围内,即便NavMesh就绪也可能生成无效位置。
具体修复步骤
1. 修正LevelManager的事件触发时机(异步加载完成后再发事件)
将LoadSelectedLevel改为协程,等待场景完全加载完成后再触发生成角色的事件:
public class LevelManager : MonoBehaviour { // 保留原有成员变量与单例逻辑... public void LoadSelectedLevel(Level level) { selectedLevel = level; StartCoroutine(LoadSceneAndTriggerEvent(level.name)); } private IEnumerator LoadSceneAndTriggerEvent(string sceneName) { AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName); // 阻塞直到场景加载完成 while (!asyncLoad.isDone) { yield return null; } // 场景加载完成后触发角色生成事件 OnLevelSelect?.Invoke(this, new OnLevelSelectEventArgs { level = selectedLevel }); } }
2. 修复RandomNavMeshLocation方法,确保生成点在NavMesh上
原方法仅生成随机球内的点,未校验NavMesh有效性,改用NavMesh.SamplePosition获取合法位置:
private Vector3 RandomNavMeshLocation(float radius) { // 以当前对象位置为中心生成随机点 Vector3 randomPoint = transform.position + Random.insideUnitSphere * radius; NavMeshHit hit; // 查找距离随机点最近的NavMesh有效位置,搜索范围设为radius if (NavMesh.SamplePosition(randomPoint, out hit, radius, NavMesh.AllAreas)) { return hit.position; } // 未找到有效点时返回当前对象位置作为备选 return transform.position; }
3. 可选:增加NavMesh就绪校验(适配大型场景)
如果场景体积较大,NavMesh生成可能滞后于场景加载完成,可在SpawnHumans中等待NavMesh就绪:
private void SpawnHumans(int numberOfPeople) { StartCoroutine(SpawnHumansAfterNavMeshReady(numberOfPeople)); } private IEnumerator SpawnHumansAfterNavMeshReady(int numberOfPeople) { // 等待NavMesh全局就绪 while (!NavMesh.IsReady()) { yield return null; } // 修正循环条件:原<=会多生成1个角色 for(int i = 0; i < numberOfPeople; i++) { float radius = 10f; Instantiate(human, RandomNavMeshLocation(radius), Quaternion.identity); } }
内容的提问来源于stack exchange,提问作者Alex Grossi
相关产品推荐
相关产品推荐

