using cfg; using System.IO; using Framework; using System.Linq; using UnityEditor; using UnityEngine; using cfg.LevelCfg; using PhxhSDK.Phxh; using Gameplay.Level; using UnityEditor.SceneManagement; public abstract class LevelValidatorBase { /// /// 错误数据 /// public bool ErrorData; /// /// 错误场景 /// protected bool ErrorScene; /// /// 错误信息 /// public string ErrorMessage; /// /// 警告信息 /// public string WarningMessage; protected LevelData LevelData; protected MapData MapData; protected readonly string LevelDataPath; protected readonly string MapDataPath; private readonly DataLevel levelCfg; protected LevelValidatorBase(string levelDataPath, string mapDataPath) { LevelDataPath = levelDataPath; MapDataPath = mapDataPath; CheckWellResourced(); } protected LevelValidatorBase(DataLevel levelCfg) { this.levelCfg = levelCfg; LevelDataPath = levelCfg.LevelData; MapDataPath = levelCfg.MapData; CheckWellResourced(); CheckMapScene(); } private void CheckMapScene() { if (levelCfg == null || string.IsNullOrEmpty(levelCfg.LevelScene) || !File.Exists(levelCfg.LevelScene)) { ErrorScene = true; AppendWithNewLine(ref ErrorMessage, "场景路径不存在,请检查资源"); return; } if (!File.Exists(GetPostScenePath())) { ErrorScene = true; AppendWithNewLine(ref ErrorMessage, $"后处理场景不存在,请先后处理{levelCfg.LevelScene}"); } } private void CheckWellResourced() { if (string.IsNullOrEmpty(LevelDataPath) || string.IsNullOrEmpty(MapDataPath)) { AppendWithNewLine(ref ErrorMessage, "地图或关卡数据为空,请检查配置表"); ErrorData = true; return; } var levelPath = string.Format(Constants.LEVEL_CONFIG_FORMAT_PATH, LevelDataPath); var mapPath = string.Format(Constants.MAP_CONFIG_FORMAT_PATH, MapDataPath); var levelAsset = AssetDatabase.LoadAssetAtPath(levelPath); var mapAsset = AssetDatabase.LoadAssetAtPath(mapPath); if (levelAsset == null || mapAsset == null) { AppendWithNewLine(ref ErrorMessage, $"【地图数据路径:{MapDataPath} / 关卡数据路径:{LevelDataPath} 】加载失败,请检查本地是否有对应数据文件"); ErrorData = true; return; } LevelData = JsonToData(levelAsset); MapData = JsonToData(mapAsset); if (LevelData == null || MapData == null) { AppendWithNewLine(ref ErrorMessage, "无法正确转换关卡和地图数据"); ErrorData = true; } } public abstract bool CheckData(); private T JsonToData(TextAsset jsonText) where T : new() { if (jsonText != null) { var jsonStr = jsonText.text; if (string.IsNullOrEmpty(jsonStr)) { return new T(); } else { var path = AssetDatabase.GetAssetPath(jsonText); return JsonHelper.LoadJson(path); } } return default; } protected bool RegionIsLegal(int regionID) { return MapData.regions.Count > regionID; } /// /// 后处理场景路径 /// private string _postScenePath; protected string GetPostScenePath() { if (ErrorScene) return null; if (!string.IsNullOrEmpty(_postScenePath)) return _postScenePath; var scenePath = levelCfg.LevelScene; var postSceneDirectory = Path.GetFileNameWithoutExtension(scenePath.Replace("/", "_")); var postScene = Path.GetFileNameWithoutExtension(scenePath) + "_PostProcess.unity"; _postScenePath = $"Assets/Art/AutoGen/PostProcessScenes/{postSceneDirectory}/{postScene}"; return _postScenePath; } protected void AppendWithNewLine(ref string original, string newString) { if (!string.IsNullOrEmpty(original)) { original += "\n"; } original += newString; } } /// /// 检查占领点是否合法 /// public class CheckCaptureData : LevelValidatorBase { public CheckCaptureData(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath) { } public override bool CheckData() { if (ErrorData) return false; if (MapData.capturePoints.Count > 0) { if (LevelData.captureProgress <= 0) { ErrorMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】有占领点,但无占领进度信息!"; return false; } } return true; } } /// /// 检查扛旗点 /// public class CheckFlagData : LevelValidatorBase { public CheckFlagData(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath) { } public override bool CheckData() { if (ErrorData) return false; if (MapData.flagStartPoints.Count > 0) { DebugUtil.Log("有扛旗起点"); if (LevelData.flagTargetRegionId == 0 && RegionIsLegal(0)) { WarningMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】有扛旗起点,扛旗终点区域为默认 0 !"; } if (!RegionIsLegal(LevelData.flagTargetRegionId)) { ErrorMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】有扛旗起点,扛旗终点区域【{LevelData.flagTargetRegionId}】不存在 !"; return false; } } return true; } } /// /// 检查关卡区域设置 /// public class CheckLevelRegionData : LevelValidatorBase { public CheckLevelRegionData(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath) { } public override bool CheckData() { if (ErrorData) return false; if (!RegionIsLegal(LevelData.preparingRegionId)) { ErrorMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】出战区【{LevelData.preparingRegionId}】错误,不存在 !"; return false; } if (!RegionIsLegal(LevelData.fallbackRegionId)) { ErrorMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】撤退区【{LevelData.fallbackRegionId}】错误,不存在 !"; return false; } if (!RegionIsLegal(LevelData.enemyFallbackRegionId)) { ErrorMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】敌方撤退区【{LevelData.enemyFallbackRegionId}】错误,不存在 !"; return false; } if (!RegionIsLegal(LevelData.pvpDefendRegionId)) { ErrorMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】PVP防守区【{LevelData.pvpDefendRegionId}】错误,不存在 !"; return false; } if (LevelData.fallbackRegionId == LevelData.enemyFallbackRegionId) { WarningMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】敌人撤退区域和我方撤退区域相同 !"; } return true; } } /// /// 检查护送相关设置 /// public class CheckProtectData : LevelValidatorBase { public CheckProtectData(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath) { } public override bool CheckData() { if (ErrorData) return false; string errorUnitIds = ""; if (LevelData.protectUnitInfos.Count > 0) { foreach (var protectUnit in LevelData.protectUnitInfos) { if (protectUnit.protectStartPoint == protectUnit.protectTargetPoint) { errorUnitIds = errorUnitIds + protectUnit.id + " "; } } } if (!string.IsNullOrEmpty(errorUnitIds)) { ErrorMessage = $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】护送对象【{errorUnitIds}】的终点和起点相同"; } return true; } } /// /// 检查是否存在后处理场景 及场景中是否有未删除的人物或载具模型 /// public class CheckScenePostProcess : LevelValidatorBase { public CheckScenePostProcess(DataLevel levelCfg) : base(levelCfg) { } public override bool CheckData() { if (ErrorData || ErrorScene) return false; var postScenePath = GetPostScenePath(); var scene = EditorSceneManager.OpenScene(postScenePath, OpenSceneMode.Additive); var rootObjects = scene.GetRootGameObjects(); if (rootObjects.Any(obj => obj.name.StartsWith("P_"))) { EditorSceneManager.CloseScene(scene, true); AppendWithNewLine(ref ErrorMessage, $"【地图: {postScenePath} 】后处理场景中有未删除的人物或载具模型"); return false; } EditorSceneManager.CloseScene(scene, true); return true; } } /// /// 检查胜利胜败阶段条件 /// public class CheckLevelCondition : LevelValidatorBase { public CheckLevelCondition(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath) { } public override bool CheckData() { if (ErrorData) return false; var stages = LevelData.stages; if (stages is { Count: <= 0 }) { AppendWithNewLine(ref ErrorMessage, $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中没有设置阶段信息"); return false; } foreach (var stage in stages) { if (stage.successCondition.conditionType == ConditionType.None) { AppendWithNewLine(ref ErrorMessage, $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中获胜目标为None"); return false; } if (stage.failConditions is { Count: <= 0 }) { AppendWithNewLine(ref ErrorMessage, $"【【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中没有设置失败阶段"); return false; } if (stage.failConditions.Any(failCondition => failCondition.conditionType == ConditionType.None)) { AppendWithNewLine(ref ErrorMessage, $"【【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中失败阶段目标为None"); return false; } } return true; } } /// /// 检查若为星级关卡 参数是否正确 /// public class CheckLevelStarTarget : LevelValidatorBase { public CheckLevelStarTarget(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath) { } public override bool CheckData() { if (ErrorData) return false; if (LevelData.scoreLevel) return true; var starTargets = LevelData.starTarget; if (starTargets is { Count: <= 0 }) { AppendWithNewLine(ref ErrorMessage, $"【【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】为星级关卡,但未设置星级目标"); return false; } if (starTargets.Any(startTarget => startTarget.conditionType == ConditionType.None)) { AppendWithNewLine(ref ErrorMessage, $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中有星级目标条件为None"); return false; } return true; } } /// /// 检查若为评分关卡 参数是否正确 /// public class CheckLevelScoreTarget : LevelValidatorBase { public CheckLevelScoreTarget(string levelDataPath, string mapDataPath) : base(levelDataPath, mapDataPath) { } public override bool CheckData() { if (ErrorData) return false; if (!LevelData.scoreLevel) return true; var scoreTargets = LevelData.scoreTarget; if (scoreTargets is { Count: <= 0 }) { AppendWithNewLine(ref ErrorMessage, $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】为评分关卡,但未设置评分目标"); return false; } foreach (var scoreTarget in scoreTargets) { if (scoreTarget.conditionType == ConditionType.None) { AppendWithNewLine(ref ErrorMessage, $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中有评分目标条件为None"); return false; } if (scoreTarget.score <= 0) { AppendWithNewLine(ref ErrorMessage, $"【地图数据:{MapDataPath} / 关卡数据:{LevelDataPath} 】中评分目标【{scoreTarget.conditionType}】的分数为 0"); return false; } } return true; } }