/// <summary> /// 返回移动到目标点的移动路径 A*算法 ,vFindPathCallBack 找到路径给个回调,直到找到路径才调用 /// </summary> /// <returns></returns> public List<Vector3> GetMoveTargetPosPath(Vector3 vCurPos, Vector3 vTargetPos,Action<List<Vector3>> vFindPathCallBack = null) { InitScenePoint(mSceneChangeDataManager.SceneID); mCurParentG = 0; mCheckCount = 0; mOpenList.Clear(); var vList = new List<Vector3>(); // 先重置状态 foreach (var vItem in mScenePointDataArr) { vItem?.ResetData(); } // 转换当前的坐标 var vCurX = GameTools.GetValueByConfigValue(vCurPos.x); var vCurZ = GameTools.GetValueByConfigValue(vCurPos.z); // 拿到位置 var vStartIndexX = (vCurX - mMinX) / mDiameter; var vStartIndexZ = (vCurZ - mMinZ) / mDiameter; if (vStartIndexX < 0 || vStartIndexX >= mMapInfoLenX || vStartIndexZ < 0 || vStartIndexZ >= mMapInfoLenZ) { Log.Error($"寻路测试:起始点{vCurPos.ToString()}超出边界"); return null; } var vStartScenePointData = mScenePointDataArr[vStartIndexX, vStartIndexZ]; var vCurMapInfo = vStartScenePointData; if (vCurMapInfo == null) { Log.Error($"寻路测试:起始点{vCurPos.ToString()}不可行走"); return null; } // 标记当前的格子关闭 vCurMapInfo.SetPointType(PointType.Close); // 先把起点周边的坐标都放入OpenList AddScenePointDataToOpenList(vCurMapInfo.Index, mCurParentG); var vTargetX = GameTools.GetValueByConfigValue(vTargetPos.x); var vTargetZ = GameTools.GetValueByConfigValue(vTargetPos.z); mTargetIndexX = (vTargetX - mMinX) / mDiameter; mTargetIndexZ = (vTargetZ - mMinZ) / mDiameter; if (mTargetIndexX < 0 || mTargetIndexX >= mMapInfoLenX || mTargetIndexZ < 0 || mTargetIndexZ >= mMapInfoLenZ) { Log.Info($"寻路测试:终点{vTargetPos.ToString()}超出边界"); return null; } var vEndScenePointData = mScenePointDataArr[mTargetIndexX, mTargetIndexZ]; if (vEndScenePointData == null) { Log.Info($"寻路测试:终点{vTargetPos.ToString()}不可行走"); return null; } mGoToNext = true; mTargetCanGo = false; while (mGoToNext) { var vIsTarget = GetMinIndexByOpenList(out var vCurScenePointData); if (vIsTarget) { // 如果是找到终点了,则直接跳出去 mGoToNext = false; mTargetCanGo = true; vList.Add(GameTools.GetConfigPosition(vCurScenePointData.Pos.x, 0, vCurScenePointData.Pos.y)); Log.Info("寻路测试:终于找到目的地了"); break; } // 下一个点,都不可走。直接跳出 if (vCurScenePointData == null) { mGoToNext = false; mTargetCanGo = false; Log.Info("寻路测试:找到死胡同了"); return null; } mCurParentG = vCurScenePointData.G; mOpenList.Remove(vCurScenePointData); vList.Add(GameTools.GetConfigPosition(vCurScenePointData.Pos.x, 0, vCurScenePointData.Pos.y)); AddScenePointDataToOpenList(vCurScenePointData.Index, mCurParentG); // TODO:保底,防止出不去 mCheckCount++; if (mCheckCount <= mCheckCountMax) continue; mGoToNext = false; mTargetCanGo = false; break; } return GetMovePath(vStartScenePointData, vEndScenePointData,vFindPathCallBack); }