/* * @Author: 白哉 * @Description: AI 编辑器 * @Date: 2025年04月22日 星期二 15:04:14 * @Modify: */ using System.Collections.Generic; using System.Linq; using CanvasCoreExpand; using Logic.AI; using NodeCanvas.BehaviourTrees; using NodeCanvas.Framework; using NodeCanvas.Tasks.Actions; using RuntimeData; using TH1_Logic.Core; using Unity.VisualScripting; using UnityEditor; using UnityEngine; namespace Logic.Editor { public enum EditorType { Asset, Tech, ScoreShow, } public class AIConfigEditorWindow : EditorWindow { // 滑条 private Vector2 _barPosition; // 背景 private GUIStyle _redBoxStyle; private GUIStyle _whiteBoxStyle; private PlayerData _player; private CityData _city; private Main _main; private AIConfigAsset _asset; [MenuItem("Tools/AI 编辑器")] private static void ShowWindow() { var window = CreateWindow(); window.titleContent = new GUIContent("AI 编辑器"); window.Show(); window.minSize = new Vector2(500, 600); } protected virtual void OnEnable() { ExpandGraphEditor.Exporter = new GraphExporter(); } private void OnDisable() { } private void OnGUI() { if (_redBoxStyle == null) { _redBoxStyle = InspectorUtils.GetHelpBoxStyle(); InspectorUtils.AddBorder(_redBoxStyle, new Color(0.5f, 0.4f, 0.4f, 0.6f)); } if (_whiteBoxStyle == null) { _whiteBoxStyle = InspectorUtils.GetHelpBoxStyle(); InspectorUtils.AddBorder(_whiteBoxStyle, new Color(1f, 1f, 1f, 0.2f)); } GUI.skin.button.wordWrap = true; _barPosition = EditorGUILayout.BeginScrollView(_barPosition); if (!Application.isPlaying) OnInspectorAIConfig(); OnGUIRunTime(); OnShowPlayerInfo(); OnShowCityInfo(); OnInspectorAIRecord(); EditorGUILayout.EndScrollView(); } private void OnInspectorAIRecord() { if (_player == null) return; var records = AILogic.GetAIRecords(_player.Id); if (records == null) return; foreach (var record in records) OnInspectorAIRecordItem(record); } private void OnInspectorAIRecordItem(AIRecord record) { EditorGUILayout.BeginVertical(_redBoxStyle); record.IsFoldout = EditorGUILayout.Foldout(record.IsFoldout, $"{record.GetDesc()}"); if (record.IsFoldout) { if (record.Action != null) { InspectorUtils.InspectorTextWidthRich($" {record.Action.ActionLogic.ActionId.GetStringLog()} "); InspectorUtils.InspectorTextWidthRich($" {record.Action.Param.GetStringLog()} "); } for (int i = record.StateRecords.Count - 1; i >= 0; i--) { var state = record.StateRecords[i]; InspectorUtils.InspectorTextWidthRich($" {state.ID} : {state.Result} : {state.Desc} "); } } EditorGUILayout.EndVertical(); EditorGUILayout.Space(); EditorGUILayout.Space(); } private void OnInspectorAIConfig() { if (!_asset) { var path = $"Assets/BundleResources/DataAssets/AIConfig.asset"; _asset = AssetDatabase.LoadAssetAtPath(path); if (!_asset) { _asset = CreateInstance(); AssetDatabase.CreateAsset(_asset, path); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } } if (InspectorUtils.InspectorButtonWithTextWidth("保存")) { EditorUtility.SetDirty(_asset); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } for (int i = (int)AIDifficult.EASY; i <= (int)AIDifficult.LUNATIC; i++) { if (_asset.GetAIDiffInfo((AIDifficult)i) == null) { _asset.AidiffInfos.Add(new AIDiffInfo((AIDifficult)i)); } } _asset.AidiffInfos = _asset.AidiffInfos.OrderBy(i => i.Level).ToList(); foreach (var diffInfo in _asset.AidiffInfos) { EditorGUILayout.BeginVertical(_whiteBoxStyle); InspectorUtils.InspectorTextWidthRich($"难度:{diffInfo.Level}"); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich($"自由人撤退攻击收益"); diffInfo.FreeUnitRetreat = EditorGUILayout.FloatField(diffInfo.FreeUnitRetreat); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich($"自由人其他攻击收益"); diffInfo.FreeUnitRetreat = EditorGUILayout.FloatField(diffInfo.FreeUnitOther); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich($"军团成员协防攻击收益"); diffInfo.FreeUnitRetreat = EditorGUILayout.FloatField(diffInfo.LegionUnitDefend); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich($"军团成员进攻攻击收益"); diffInfo.FreeUnitRetreat = EditorGUILayout.FloatField(diffInfo.LegionUnitAttack); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich($"军团成员驻扎攻击收益"); diffInfo.FreeUnitRetreat = EditorGUILayout.FloatField(diffInfo.LegionUnitDevelopment); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); InspectorUtils.InspectorTextWidthRich($"城中小兵攻击收益"); diffInfo.FreeUnitRetreat = EditorGUILayout.FloatField(diffInfo.UnitInCity); EditorGUILayout.EndHorizontal(); EditorGUILayout.EndVertical(); } } private void OnGUIRunTime() { if (!Application.isPlaying) return; if (!_main) { var obj = GameObject.Find("Main"); if (!obj) return; _main = obj.GetComponent
(); if (!_main) return; } if (Main.MapData == null) return; EditorGUILayout.BeginHorizontal(); foreach (var player in Main.MapData.PlayerMap.PlayerDataList) { if (player.Id == Main.MapData.PlayerMap.SelfPlayerId) continue; if (InspectorUtils.InspectorButtonWithTextWidth($"玩家{player.Id}")) _player = player; } EditorGUILayout.EndHorizontal(); var selfCity = new HashSet(); Main.MapData.GetCityDataListByPlayerId(Main.MapData.PlayerMap.SelfPlayerId, selfCity); EditorGUILayout.BeginHorizontal(); foreach (var city in Main.MapData.CityMap.CityList) { if (selfCity.Contains(city)) continue; if (InspectorUtils.InspectorButtonWithTextWidth($"城市{city.Id}")) _city = city; } EditorGUILayout.EndHorizontal(); } private void OnShowPlayerInfo() { if (Main.MapData == null || _player == null) return; MainEditor.Instance.GetPlayerStrategy(_player.Id, out var playerStrategy, out var targetIdSet); EditorGUILayout.BeginHorizontal(); if (playerStrategy != Strategy.Attack) InspectorUtils.InspectorTextWidthRich($"玩家ID: {_player.Id}, 国家战略为: {playerStrategy}"); else { var idStr = ""; foreach (var id in targetIdSet) idStr += $"{id}"; InspectorUtils.InspectorTextWidthRich( $"玩家ID: {_player.Id}, 国家战略为: {playerStrategy}, 目标:{idStr}"); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginVertical(_redBoxStyle); InspectorUtils.InspectorTextWidthRich($"城市信息"); var selfCity = new HashSet(); Main.MapData.GetCityDataListByPlayerId(_player.Id, selfCity); foreach (var city in selfCity) { MainEditor.Instance.GetCityStrategy(city.Id, out var strategy); InspectorUtils.InspectorTextWidthRich($"ID: {city.Id}, 策略: {strategy}"); } EditorGUILayout.EndVertical(); EditorGUILayout.Space(); EditorGUILayout.Space(); EditorGUILayout.BeginVertical(_redBoxStyle); InspectorUtils.InspectorTextWidthRich($"小兵信息"); var selfUnits = new HashSet(); Main.MapData.GetUnitDataListByPlayerId(_player.Id, selfUnits); foreach (var unit in selfUnits) { MainEditor.Instance.GetUnitStrategy(unit.Id, unit.LegionId, _player.Id, out var strategy, out var target, out var type); InspectorUtils.InspectorTextWidthRich(unit.LegionId == 0 ? $"ID: {unit.Id}, 自由人, 策略: {strategy}, 目标城市: {target}" : $"ID: {unit.Id}, 军团ID:{unit.LegionId}, 策略: {strategy}, 类型:{type}, 目标城市: {target}"); } EditorGUILayout.EndVertical(); } private void OnShowCityInfo() { if (Main.MapData == null || _city == null) return; var actions = MainEditor.Instance.GetCityActions(_city.Id); if (actions == null || actions.Count == 0) return; foreach (var aiAction in actions) { EditorGUILayout.BeginVertical(_whiteBoxStyle); if (aiAction.Param.GridData != null) InspectorUtils.InspectorTextWidthRich($"位置: {aiAction.Param.GridData.Pos.X}, {aiAction.Param.GridData.Pos.Y}"); InspectorUtils.InspectorTextWidthRich($"ActionType: {aiAction.ActionLogic.ActionId.ActionType}"); InspectorUtils.InspectorTextWidthRich($"WonderType: {aiAction.ActionLogic.ActionId.WonderType}"); InspectorUtils.InspectorTextWidthRich($"ResourceType: {aiAction.ActionLogic.ActionId.ResourceType}"); InspectorUtils.InspectorTextWidthRich($"FeatureType: {aiAction.ActionLogic.ActionId.FeatureType}"); InspectorUtils.InspectorTextWidthRich($"TerrainType: {aiAction.ActionLogic.ActionId.TerrainType}"); InspectorUtils.InspectorTextWidthRich($"UnitType: {aiAction.ActionLogic.ActionId.UnitType}"); InspectorUtils.InspectorTextWidthRich($"GiantType: {aiAction.ActionLogic.ActionId.GiantType}"); InspectorUtils.InspectorTextWidthRich($"Vegetation: {aiAction.ActionLogic.ActionId.Vegetation}"); InspectorUtils.InspectorTextWidthRich($"UnitActionType: {aiAction.ActionLogic.ActionId.UnitActionType}"); InspectorUtils.InspectorTextWidthRich($"CityLevelUpActionType: {aiAction.ActionLogic.ActionId.CityLevelUpActionType}"); InspectorUtils.InspectorTextWidthRich($"GridMiscActionType: {aiAction.ActionLogic.ActionId.GridMiscActionType}"); InspectorUtils.InspectorTextWidthRich($"SkillType: {aiAction.ActionLogic.ActionId.SkillType}"); InspectorUtils.InspectorTextWidthRich($"TechType: {aiAction.ActionLogic.ActionId.TechType}"); EditorGUILayout.EndVertical(); EditorGUILayout.Space(); } } } }