using System; using cfg.LevelCfg; using System.Collections.Generic; using Gameplay.Area; using Gameplay.Buff; using Gameplay.Character; using GamePlay.Fight.Weapon; using Gameplay.Level; using Gameplay.Unit; using Gameplay.Unit.Data; using Gameplay.Skill; using Gameplay.Vehicle; using Gameplay.Vehicle.Impl; using UnityEngine; using UnityEditor; namespace FightDebug { public class SingleUnitWindow : EditorWindow { private Vector2 _scrollPos1; private GameUnit _targetUnit; private int _pureDamageValue = 100; public static void ShowWindow(GameUnit unit) { var win = GetWindow("单位:" + unit.GetDescString()); win._targetUnit = unit; win.Show(); win.Focus(); } private bool _CheckCanShow() { if (!Application.isPlaying) { return false; } if (LevelManager.Instance == null) { return false; } if (GameUnitManager.instance == null) { return false; } return true; } private void _ShowNotInFight() { EditorGUILayout.HelpBox("仅支持在开战后使用", MessageType.Error); } private void _ShowLabel(string label, string value) { GUILayout.BeginHorizontal(); GUILayout.Label(label, GUILayout.Width(140)); GUILayout.Label(value); GUILayout.EndHorizontal(); } private void _ShowIcon(string iconPath) { GUILayout.BeginHorizontal(); GUILayout.Label("头像:", GUILayout.Width(140)); GUILayout.Label(new GUIContent(_LoadIcon(iconPath)), GUILayout.Width(100), GUILayout.Height(100)); GUILayout.EndHorizontal(); } private Texture2D _LoadIcon(string iconPath) { const string defaultIconPath = "Assets/_Test/Texture/no_pic.png"; if (string.IsNullOrEmpty(iconPath)) { return AssetDatabase.LoadAssetAtPath(defaultIconPath); } if (!iconPath.StartsWith("Assets/")) { return AssetDatabase.LoadAssetAtPath(defaultIconPath); } var iconObj = AssetDatabase.LoadAssetAtPath(iconPath); if (iconObj == null) { return AssetDatabase.LoadAssetAtPath(defaultIconPath); } return iconObj; } private void _ShowProgress(string label, int currentValue, int maxValue) { GUILayout.BeginHorizontal(GUILayout.Height(40)); GUILayout.Label(label, GUILayout.Width(140)); if (maxValue == 0) { GUILayout.Label("-无-"); } else { GUILayout.BeginVertical(); var progress = 1f * currentValue / maxValue; var progressStr = $"{currentValue}/{maxValue} ({progress:P})"; GUILayout.Label(progressStr); GUILayout.HorizontalSlider(progress, 0, 1); GUILayout.EndVertical(); } GUILayout.EndHorizontal(); } private void _ShowBuff(BaseBuff buff) { GUILayout.BeginVertical("box"); _DisplayBuffIcon(buff); _ShowLabel("名字:", buff.configData.Name); _ShowLabel("BuffId:", buff.configData.ID + ""); _ShowLabel("Level:", buff.configData.Level + ""); GUILayout.EndVertical(); } private void _DisplayBuffIcon(BaseBuff buff) { // Assets/Art/UI/Texture/Icon/BuffIcon/UI_Armor.png var displayIcon = buff.configData.BuffDisplayIcon; if (string.IsNullOrEmpty(displayIcon)) { GUILayout.Label("无图标"); return; } var iconPath = "Assets/Art_Out/UI/Texture/Icon/BuffIcon/" + displayIcon + ".png"; var icon = _LoadIcon(iconPath); if (icon == null) { EditorGUILayout.HelpBox("无法找到图标:" + displayIcon, MessageType.Error); } else { GUILayout.BeginHorizontal(); GUILayout.Label("图标:", GUILayout.Width(140)); var originWidth = icon.width; var originHeight = icon.height; var scaleSize = 40f / originWidth; GUILayout.Label(new GUIContent(icon), GUILayout.Width(originWidth * scaleSize), GUILayout.Height(originHeight * scaleSize)); GUILayout.EndHorizontal(); } } private void _ShowDebugArea(List cellIndexs) { var fakeParent = new GameObject("FakeParent").transform; for (int i = 0; i < cellIndexs.Count; i++) { var worldPos = AreaManager.instance.GetWorldPosByIndex(cellIndexs[i]); // 在对应位置创建一个球体 var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); sphere.transform.SetParent(fakeParent); sphere.transform.position = worldPos; } } private void _ShowBelongBuild() { var belongBuild = _targetUnit.commonData.belongBuild; _ShowLabel("是否有所属建筑:", belongBuild != null ? "是" : "否"); if (belongBuild == null) return; _ShowLabel("所属建筑ID:", belongBuild.GetID() + ""); _ShowLabel("所属建筑名字:", belongBuild.configData.rawConfig.Name); } private void _ShowDamageRecord() { var levelNowTime = LevelManager.Instance.CurrentLevel.LevelTime; var recordStartTime = _targetUnit.damageRecord.BeginTime; var passTime = levelNowTime - recordStartTime; GUILayout.Label("伤害记录", EditorStyles.boldLabel); _ShowLabel("伤害记录经过时间:", passTime + "秒"); GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); _ShowLabel("总平A伤害:",_targetUnit.damageRecord.NormalDamageCount.ToString("F2")+"点"); _ShowLabel("平A秒伤",(_targetUnit.damageRecord.NormalDamageCount/passTime).ToString("F2")+"点/秒"); GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); _ShowLabel("总技能伤害",_targetUnit.damageRecord.SkillDamageCount.ToString("F2")+"点"); _ShowLabel("技能秒伤",(_targetUnit.damageRecord.SkillDamageCount/passTime).ToString("F2")+"点/秒"); GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); _ShowLabel("总环境伤害",_targetUnit.damageRecord.EnvironmentDamageCount.ToString("F2")+"点"); _ShowLabel("环境秒伤",(_targetUnit.damageRecord.EnvironmentDamageCount/passTime).ToString("F2")+"点/秒"); GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); _ShowLabel("总记录值:", _targetUnit.damageRecord.TotalDamageCount.ToString("F2") + "点"); _ShowLabel("总伤害平均秒伤:", (_targetUnit.damageRecord.TotalDamageCount / passTime).ToString("F2") + "点/秒"); if (GUILayout.Button("清零")) { _targetUnit.damageRecord.Clear(); } } private void _ShowBulletRecord() { GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); GUILayout.Label("子弹记录", EditorStyles.boldLabel); _ShowLabel("当前子弹数量",$"{_targetUnit.fightData.mainWeaponData.remainBulletCount}"); _ShowLabel("最大子弹数量",$"{_targetUnit.bulletRecord.MaxBulletCount}"); _ShowLabel("换弹前子弹数量",_targetUnit.bulletRecord.PreReloadRemainBulletCount!=-1?$"{_targetUnit.bulletRecord.PreReloadRemainBulletCount}":"从未换弹"); _ShowLabel("补充子弹数量",$"{_targetUnit.bulletRecord.ReloadBulletCount}"); _ShowLabel("换弹后子弹数量",$"{_targetUnit.bulletRecord.AfterReloadRemainBulletCount}"); GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); } private void _ShowDealDamage() { GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); GUILayout.Label("造成伤害", EditorStyles.boldLabel); GUILayout.BeginHorizontal(); GUILayout.Label("伤害数值:", GUILayout.Width(140)); _pureDamageValue = EditorGUILayout.IntField(_pureDamageValue); GUILayout.EndHorizontal(); if (GUILayout.Button("造成伤害")) { var weaponData = GameUnitManager.instance.playerUnit.fightData.mainWeaponData; _targetUnit.TakePureDamage(_pureDamageValue, weaponData); } GUILayout.Box("", GUILayout.Height(1), GUILayout.ExpandWidth(true)); } private void _ShowAvoidBuffIds() { if (_targetUnit.buffManager?.avoidBuffManager?.avoidBuffIds == null) { _ShowLabel("免疫Buff数量:", "无数据"); return; } _ShowLabel("免疫Buff数量:", _targetUnit.buffManager.avoidBuffManager.avoidBuffIds.Count + "种"); for (int i = 0; i < _targetUnit.buffManager.avoidBuffManager.avoidBuffIds.Count; i++) { var avoidBuffId = _targetUnit.buffManager.avoidBuffManager.avoidBuffIds[i]; var avoidRecordCount = _targetUnit.buffManager.avoidBuffManager.recordCountList[i]; _ShowLabel("-", $"{avoidBuffId}:{avoidRecordCount}"); } } private void _ShowDodgeValue() { _ShowLabel("闪避值:", _targetUnit.fightData.dodgeRateValue + ""); _ShowLabel("闪避修正率(最终闪避率):", _targetUnit.fightData.dodgeRateFixPercent + ""); } private void _ShowInvestigateInfo() { var dict = _targetUnit.fightData.dicInvestigateStrength; var combineStr = ""; foreach (var kv in dict) { var key = kv.Key; var value = kv.Value; combineStr += $"{key}:{value},"; } _ShowLabel("侦查强度:", combineStr); _ShowLabel("隐蔽类型:", _targetUnit.fightData.CoverType + ""); _ShowLabel("隐蔽强度:", _targetUnit.fightData.CoverStrength + ""); _ShowLabel("侦查距离:", _targetUnit.fightData.searchDistance + "格"); } private void _ShowInFight() { var unit = _targetUnit; _scrollPos1 = GUILayout.BeginScrollView(_scrollPos1, GUILayout.Width(420)); GUILayout.BeginVertical("box",GUILayout.Width(390)); try { _ShowLabel("ID:", unit.GetID() + ""); _ShowLabel("类型:", EGameUnitTypeUtils.GetStrByType(unit.gameunitType)); _ShowLabel("名字:", unit.debugShowInfo.name); _ShowLabel("配置ID:", unit.debugShowInfo.configId); _ShowLabel("阵营ID:", unit.commonData.troopId + ""); if (unit.commonData.troopId == ETroopsId.Enemy && unit.unitLevelData != null) { _ShowLabel("怪物品质:", unit.unitLevelData.monsterQualityType.ToString()); } _ShowIcon(unit.debugShowInfo.iconPath); _ShowLabel("单位高度:", unit.fightData.unitHeight + ""); _ShowDefense(unit); if (unit.fightData?.mainWeaponData != null) { _ShowWeaponData("主武器", unit.fightData.mainWeaponData); } else { _ShowLabel("武器:", "无数据"); } _ShowLabel("护甲级别:", unit.fightData.defensePowerLevel + ""); _ShowLabel("配置是否允许撤离:", unit.fightData.canEvacuate ? "是" : "否"); _ShowLabel("移动速度:", unit.fightData.moveSpeed + ""); _ShowAvoidBuffIds(); _ShowDodgeValue(); _ShowInvestigateInfo(); _ShowSkillChargeInfo(unit); _ShowDamageRecord(); _ShowBulletRecord(); _ShowDealDamage(); _ShowBelongBuild(); _ShowUnitExt(); if (unit.fightData?.mainWeaponData != null) { if (GUILayout.Button("显示攻击范围")) { var centerCellIndex = unit.transData.cellIndex; var attackDistance = unit.fightData.mainWeaponData.attackDistance; var attackArea = AreaManager.instance.attackAreaManager.GetAttackArea(centerCellIndex, attackDistance); var isIgnoreBlock = unit.fightData.mainWeaponData.isAttackIgnoreBlock; var attackCells = isIgnoreBlock ? attackArea.totalCells : attackArea.canAttackCells; _ShowDebugArea(attackCells); } } _ShowProgress("生命值:", unit.aliveData.currentHp, unit.aliveData.maxHp); _ShowProgress("护甲值:", unit.aliveData.currentShield, unit.aliveData.maxShield); _ShowProgress("士气值:", unit.aliveData.currentMorale, unit.aliveData.maxMorale); if (unit.buffManager?.totalBuffList != null) { var allBuff = unit.buffManager.totalBuffList; _ShowLabel("Buff数量:", allBuff.Count + "个"); for (int i = 0; i < allBuff.Count; i++) { var buff = allBuff[i]; _ShowBuff(buff); } } else { _ShowLabel("Buff数量:", "无数据"); } } catch (System.Exception e) { _ShowLabel("错误:", e.Message); UnityEngine.Debug.LogError($"SingleUnitWindow._ShowInFight 错误: {e}"); } GUILayout.EndVertical(); GUILayout.EndScrollView(); } private void _ShowSkillChargeInfo(GameUnit unit) { var unitSkillMgr = SkillManager.instance?.GetUnitSkillManager(unit); var positiveSkill = unitSkillMgr?.positiveSkill; if (positiveSkill?.chargeLogic == null) { _ShowLabel("技能充能:", "无主动技能"); return; } var charge = positiveSkill.chargeLogic; _ShowLabel("充能方式:", charge.chargeType.ToString()); _ShowLabel("充能百分比:", charge.chargeProgress.ToString("P2")); _ShowLabel("当前储存次数:", charge.nowStoreCount + "次"); } private void _ShowDefense(GameUnit unit) { if (unit.fightData.supportDirectionalDefense) { GUILayout.BeginVertical("box"); GUILayout.Label("各向防御力", EditorStyles.boldLabel); for (int i = 0; i < (int)EDefenseDirection.Max; i++) { var dir = (EDefenseDirection)i; var defValue = unit.fightData.GetDirectionalDefense(dir); var defLevel = unit.fightData.GetDirectionalDefensePowerLevel(dir); _ShowLabel($"{_GetDirectionName(dir)}防御力:", $"{defValue} (护甲级别:{defLevel})"); } GUILayout.EndVertical(); } else { _ShowLabel("防御力:", unit.fightData.defense + ""); } } private string _GetDirectionName(EDefenseDirection dir) { switch (dir) { case EDefenseDirection.Front: return "前方"; case EDefenseDirection.Right: return "右侧"; case EDefenseDirection.Left: return "左侧"; case EDefenseDirection.Back: return "后方"; case EDefenseDirection.Up: return "上方"; case EDefenseDirection.Down: return "下方"; default: return dir.ToString(); } } private void _ShowUnitExt() { switch (_targetUnit.gameunitType) { case EGameUnitType.Vehicle: _ShowVehicleExt(); break; } } private void _ShowVehicleExt() { var normalVehicle = _targetUnit as NormalVehicle; if (normalVehicle == null) { EditorGUILayout.HelpBox("当前单位不是普通载具", MessageType.Error); return; } _ShowBattery(normalVehicle.mainBattery); for (int i = 0; i < normalVehicle.subBatteryList.Count; i++) { var extBattery = normalVehicle.subBatteryList[i]; _ShowBattery(extBattery); } } private void _ShowBattery(BaseBattery battery) { var title = $"炮台[{battery.rawConfig.ID}] {battery.rawConfig.NameRead}"; _ShowLabel("炮台类型:", battery.rawConfig.BatteryType.ToString()); _ShowLabel("是否可以平A:", battery.rawConfig.CanAttack ? "是" : "否"); _ShowLabel("炮台转动速度:", battery.runtimeData.turnSpeed.ToString("F2") + "°/s"); _ShowWeaponData(title, battery.bindWeaponData); } private void _ShowWeaponData(string title, UnitWeaponData wd) { GUILayout.BeginVertical("box"); GUILayout.Label(title, EditorStyles.boldLabel); _ShowLabel("攻击力:", wd.attack + ""); _ShowLabel("穿甲级别:", wd.attackPowerLevel + ""); _ShowLabel("攻击距离:", wd.attackDistance + "格"); _ShowLabel("射速:", wd.shootCd > 0 ? (1f / wd.shootCd).ToString("F2") : "0"); _ShowLabel("攻击间隔(shootCd):", wd.shootCd.ToString("F3") + "秒"); _ShowLabel("暴击率:", wd.criticalRate.ToString("P2")); _ShowLabel("暴击伤害倍率:", wd.criticalDamageScale.ToString("F2") + "x"); _ShowLabel("士气伤害:", wd.moraleAttack.ToString("F2")); _ShowLabel("士气伤害倍率:", wd.moraleDamageScale.ToString("F2") + "x"); _ShowLabel("换弹时间:", wd.clampedReloadTime.ToString("F2") + "秒"); _ShowLabel("举枪时间:", wd.clampedRaiseWeaponTime.ToString("F2") + "秒"); _ShowLabel("攻击间隔时间:", wd.clampedAttackEndTime.ToString("F2") + "秒"); _ShowLabel("命中值:", wd.hitRateValue + ""); _ShowLabel("命中修正率:", wd.hitRateFixPercent + ""); _ShowLabel("剩余子弹数:", wd.remainBulletCount + "发"); _ShowLabel("最大子弹数:", wd.maxBulletCount + "发"); _ShowLabel("抬枪状态:", wd.isInRaisingWeapon ? "是" : "否"); _ShowLabel("射击状态:", wd.isInShooting ? "是" : "否"); _ShowLabel("换弹状态:", wd.isInReloading ? "是" : "否"); _ShowLabel("射击后间隔:", wd.isInAttackEnd ? "是" : "否"); GUILayout.EndVertical(); } private void OnGUI() { if (_CheckCanShow()) { _ShowInFight(); } else { _ShowNotInFight(); // 关闭窗口 Close(); } } } }