NLDClient-yudde/ProjectNLD/Assets/Editor/LevelEditor/LevelEditorWindow.cs

884 lines
29 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using TGS;
using System;
using Gameplay;
using Framework;
using System.IO;
using UnityEditor;
using UnityEngine;
using System.Linq;
using cfg.FightCfg;
using Gameplay.Utils;
using Gameplay.Level;
using Sirenix.Utilities;
using Gameplay.Level.Data;
using Sirenix.OdinInspector;
using Sirenix.Utilities.Editor;
using UnityEngine.Serialization;
using System.Collections.Generic;
using Sirenix.OdinInspector.Editor;
using Constants = Framework.Constants;
using ObjectFieldAlignment = Sirenix.OdinInspector.ObjectFieldAlignment;
public class LevelEditorWindow : OdinEditorWindow
{
private static readonly Color regionColor = MapUtils.GetRGBAColor("FF960072");
[Serializable]
public class RegionData
{
[LabelText("出战区")] [OnValueChanged("OnRegionChanged")]
public int preparingRegionId;
[LabelText("出战区朝向")] public LevelData.CharacterToward preparingRegionToward;
[LabelText("撤退区")] public int fallbackRegionId;
[LabelText("敌方撤退区")] public int enemyFallbackRegionId;
[LabelText("PVP防守区")] public int pvpDefendRegionId;
[LabelText("PVP防守方朝向")] public LevelData.CharacterToward pvpDefendToward;
[LabelText("扛旗终点区")] [ShowIf("needSetFlagRegion")]
public int flagTargetRegionId;
[LabelText("占领进度")] [ShowIf("needSetCaptureProgress")]
public int captureProgress;
[HideInInspector] public bool needSetFlagRegion;
[HideInInspector] public bool needSetCaptureProgress;
private void OnRegionChanged()
{
var regionsList = currWindow._curMap.MapData.regions;
for (int i = 0; i < regionsList.Count; i++)
{
currWindow._curMap.SetRegionColor(i, false, regionColor);
}
currWindow._curMap.SetRegionColor(preparingRegionId, true, regionColor);
}
}
[Serializable]
public class NPCEditorInfo
{
[ReadOnly] [LabelText("序号ID")] public int id;
[LabelText("MonsterID")] [ValueDropdown("GetMonsterIDs")] [OnValueChanged("ChangeNpcID")]
public int monsterId;
private IEnumerable<int> GetMonsterIDs()
{
return currWindow.GetMonsterIDs();
}
private void ChangeNpcID()
{
currWindow.ChangeNpcID(npcInfo, monsterId);
}
[LabelText("朝向")] [OnValueChanged("NpcTowardOnChange")]
public LevelData.CharacterToward npcToward;
private void NpcTowardOnChange()
{
npcInfo.npcToward = npcToward;
currWindow.ChangeNpcToward(npcInfo.position, npcToward);
}
[HideLabel] public LevelData.NPCInfo npcInfo;
public NPCEditorInfo(LevelData.NPCInfo npcInfo, int index)
{
this.npcInfo = npcInfo;
monsterId = npcInfo.id;
id = index;
}
[LabelText("位置调整")] [OnValueChanged("ChangeNpcPos")]
public bool isChangePos;
private void ChangeNpcPos()
{
if (isChangePos)
{
currWindow.isEditingPatrolInfo = false;
if (currWindow._currEditingNPCInfo != null)
DebugUtil.LogWarning("检查其他怪物是否处于位置调整或编辑巡逻信息状态");
}
currWindow.isEditingNpcPos = isChangePos;
currWindow._currEditingNPCInfo = isChangePos ? npcInfo : null;
}
[LabelText("显示该怪物序号")] [OnValueChanged("ShowNpcID")]
public bool isShowNpcID;
private void ShowNpcID()
{
if (isShowNpcID && !currWindow._showNpcInfos.Contains(this))
currWindow._showNpcInfos.Add(this);
else
{
currWindow._showNpcInfos.Remove(this);
}
}
private bool _isEditing;
[Button("开始编辑巡逻信息")]
[HideIf("_isEditing")]
private void StartEditNpc()
{
currWindow.StartEditPatrolInfo(npcInfo);
_isEditing = true;
}
[Button("完成编辑巡逻信息")]
[ShowIf("_isEditing")]
private void FinishEditNpc()
{
currWindow.FinishEditPatrolInfo();
_isEditing = false;
}
}
[Serializable]
public class ProtectEditorInfo
{
[HorizontalGroup("Protect")] [HideLabel]
public LevelData.ProtectUnit protectUnitInfo;
[HorizontalGroup("Protect")]
[TableColumnWidth(50, Resizable = false)]
[PreviewField(150, ObjectFieldAlignment.Center)]
[LabelText("护送对象预览图")]
[AssetList(Path = Constants.LEVEL_PROTECT_UNIT_PATH)]
[OnValueChanged("OnProtectUnitChanged")]
public GameObject protectUnitPrefab;
public ProtectEditorInfo(LevelData.ProtectUnit protectUnitInfo)
{
this.protectUnitInfo = protectUnitInfo;
InitData();
}
private void InitData()
{
prefabPathDic = new Dictionary<string, int>();
var protectCfg = EditorTableManager.instance.tables.ProtectUnitConfig;
dataProtectUnits = protectCfg.DataList;
foreach (var data in dataProtectUnits)
{
prefabPathDic.Add(data.PrefabPath, data.ID);
}
if (protectCfg.DataMap.TryGetValue(protectUnitInfo.id, out var dataConfig))
{
protectUnitPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(dataConfig.PrefabPath);
if (protectUnitPrefab == null)
DebugUtil.LogError("检查 ProtectUnitConfig 表该ID: {0} 没有对应模型配置", protectUnitInfo.id);
}
}
private void OnProtectUnitChanged()
{
if (prefabPathDic == null)
{
InitData();
}
var path = AssetDatabase.GetAssetPath(protectUnitPrefab);
if (!prefabPathDic.TryGetValue(path, out var id))
{
DebugUtil.LogError("检查 ProtectUnitConfig 表,该模型没有对应配置: {0}", path);
}
else
{
protectUnitInfo.id = id;
}
}
private Dictionary<string, int> prefabPathDic;
private List<DataProtectUnit> dataProtectUnits;
}
private static LevelEditorWindow currWindow;
private MapManager _mapManager;
private Dictionary<Vector2Int, GameObject> _npcObjectDic;
private Map _curMap;
private LevelEditor _levelEditor;
private LevelData.NPCInfo _currEditingNPCInfo;
private bool isEditingPatrolInfo;
private bool isEditingNpcPos;
private bool isShowNpcID => _showNpcInfos != null && _showNpcInfos.Count > 0;
private List<NPCEditorInfo> _showNpcInfos;
private bool ResponseClickOnCell => isEditingNPC || isEditingPatrolInfo;
[LabelText("当前关卡数据"), Indent] [OnValueChanged("OnCurrentLevelDataChanged")]
public LevelData currentLevelData = null;
[LabelText("当前地区数据"), Indent] [OnValueChanged("OnCurrentLevelDataChanged")]
public RegionData curRegionData = null;
[LabelText("编辑NPC"), Indent] [HorizontalGroup("NPC")] [LabelWidth(100)] [SerializeField]
public bool isEditingNPC;
[LabelText("显示索引地图"), Indent] [HorizontalGroup("NPC/1")] [LabelWidth(100)] [OnValueChanged("ShowCellCoordinates")] [SerializeField]
public bool isShowCellCoordinates;
private void ShowCellCoordinates()
{
if (_curMap == null || _curMap.TerrainGridSystem == null) return;
_curMap.TerrainGridSystem.displayCellDebugInfo = isShowCellCoordinates ? CellDebugInfo.CellCoordinates : CellDebugInfo.Nothing;
var obj = FindObjectOfType<TerrainGridSystem>().gameObject;
Selection.activeGameObject = obj;
}
/// <summary>
/// 关卡ID 通过关卡数据 json文件名 获得
/// </summary>
[FormerlySerializedAs("LevelID")]
[LabelText("手动指定关卡ID"), Indent]
[LabelWidth(100)]
[SerializeField]
[ShowIf("NeedManualInputLevelID")]
[OnValueChanged("GetLevelMonsterClass")]
[InfoBox("无法正确获得关卡ID请手动指定")]
public string levelID;
[LabelText("怪物ID"), Indent]
[LabelWidth(100)]
[SerializeField]
[OnValueChanged("MonsterIDChanged")]
[ValueDropdown("GetMonsterIDs")]
[ShowIf("isEditingNPC")]
public int curMonsterID;
[PreviewField(150, ObjectFieldAlignment.Center), Indent, ReadOnly] [LabelText("NPC预制体预览图"), ShowIf("isEditingNPC")]
public GameObject npcObject;
//当前怪物类ID
private int _curMonsterClassID;
private IEnumerable<int> GetMonsterIDs()
{
return monsterIDs;
}
private void MonsterIDChanged()
{
var obj = LoadNpcPrefab(curMonsterID);
if (obj != null)
npcObject = obj;
}
[LabelText("显示所有怪物序号ID"), Indent] [OnValueChanged("ShowAllNpcId")] [SerializeField]
public bool isShowAllNpcID;
private void ShowAllNpcId()
{
foreach (var npc in currentNpcInfo)
{
npc.isShowNpcID = isShowAllNpcID;
if (isShowAllNpcID)
{
if (!_showNpcInfos.Contains(npc))
{
_showNpcInfos.Add(npc);
}
}
else
{
_showNpcInfos.Remove(npc);
}
}
}
[LabelText("当前怪物列表"), Indent] [ListDrawerSettings(HideAddButton = true, HideRemoveButton = true)]
public List<NPCEditorInfo> currentNpcInfo = null;
[LabelText("编辑护送对象"), Indent] public bool isEditingProtectUnit;
[LabelText("护送对象列表"), ShowIf("isEditingProtectUnit"), Indent]
public List<ProtectEditorInfo> currentProtectUnits = null;
[Button("保存当前关卡"), Indent]
private void SaveCurrentLevel()
{
CheckCorrectLevel();
//var configFilePath = string.Format(Constants.LEVEL_CONFIG_FORMAT_PATH, currentLevelData.id);
currentLevelData.preparingRegionId = curRegionData.preparingRegionId;
currentLevelData.fallbackRegionId = curRegionData.fallbackRegionId;
currentLevelData.enemyFallbackRegionId = curRegionData.enemyFallbackRegionId;
currentLevelData.preparingRegionToward = curRegionData.preparingRegionToward;
currentLevelData.pvpDefendRegionId = curRegionData.pvpDefendRegionId;
currentLevelData.pvpDefendToward = curRegionData.pvpDefendToward;
//NPC列表
currentLevelData.npcInfos = currentNpcInfo.Select(editorNPCInfo => editorNPCInfo.npcInfo).ToList();
//占领进度 抗旗终点
currentLevelData.captureProgress = curRegionData.captureProgress;
currentLevelData.flagTargetRegionId = curRegionData.flagTargetRegionId;
//护送对象
currentLevelData.protectUnitInfos =
currentProtectUnits.Select(editorProtectInfo => editorProtectInfo.protectUnitInfo).ToList();
_levelEditor.SaveLevelData();
}
public static void OpenWindow(LevelEditor levelEditor)
{
MapEditorSettings.Init();
currWindow = GetWindow<LevelEditorWindow>();
currWindow.position = GUIHelper.GetEditorWindowRect().AlignCenter(800, 600);
currWindow.currentLevelData = null;
currWindow._levelEditor = levelEditor;
currWindow.LoadLevel(levelEditor.LevelData);
var level = Path.GetFileNameWithoutExtension(levelEditor.LevelDataJson.name);
currWindow.levelID = level.Substring(level.Length - 6);
currWindow.GetLevelMonsterClass();
currWindow.CheckFlagAndCapture();
DebugUtil.Log("关卡数据:{0}", currWindow.levelID);
}
/// <summary>
/// 该关卡的怪物ID
/// </summary>
[HideInInspector] public List<int> monsterIDs;
/// <summary>
/// 需要手动输入关卡ID
/// </summary>
[HideInInspector] public bool NeedManualInputLevelID;
public void GetLevelMonsterClass()
{
var levelCfg = EditorTableManager.instance.tables.Level;
if (!int.TryParse(levelID, out var levelIndex) ||
!levelCfg.DataMap.TryGetValue(levelIndex, out var level))
{
NeedManualInputLevelID = true;
DebugUtil.LogError("无对应的关卡ID请手动输入关卡ID");
curMonsterID = 0;
npcObject = null;
return;
}
monsterIDs = new List<int>();
var monsterCfg = EditorTableManager.instance.tables.Monster;
foreach (var monster in monsterCfg.DataMap)
{
var strID = monster.Key.ToString();
var tempID = strID.Substring(0, 6);
//关卡ID相同
if (tempID.Equals(levelID))
{
monsterIDs.Add(monster.Key);
}
}
if (monsterIDs.Count <= 0)
{
DebugUtil.LogError("请检查Monster表没有{0}关卡的怪物数据", levelID);
}
}
private void CheckFlagAndCapture()
{
curRegionData.needSetFlagRegion = _curMap.MapData.flagStartPoints.Count > 0;
curRegionData.needSetCaptureProgress = _curMap.MapData.capturePoints.Count > 0;
}
private const string PreparingRegionErrorMessage = "关卡出战区设置错误,该地图没有:<{0}>号地区。\n";
private const string FallbackRegionErrorMessage = "关卡撤退区设置错误,该地图没有:<{0}>号地区。\n";
private const string EnemyFallbackRegionErrorMessage = "关卡敌方撤退区设置错误,该地图没有:<{0}>号地区。\n";
private const string FlagTargetRegionErrorMessage = "抗旗终点区设置错误,该地图没有:<{0}>号地区。\n";
private const string ProtectUnitInfoErrorMessage = "护送 {0} 的起点和终点相同或出错,请检查。\n";
private const string FixedMessage = "已将错误区域设置为默认<0>号地区。";
private void CheckCorrectLevel()
{
if (_curMap == null)
{
return;
}
if (curRegionData.needSetCaptureProgress && curRegionData.captureProgress == 0)
DebugUtil.LogError("该地图有占领地格,无占领进度");
if (curRegionData.needSetFlagRegion && curRegionData.flagTargetRegionId <= 0)
DebugUtil.LogError("该地图有抗旗地格抗旗终点区似乎无修改默认为0号区域");
var errorMessage = string.Empty;
if (!_curMap.MapData.IsRegionExist(curRegionData.preparingRegionId))
{
errorMessage += string.Format(PreparingRegionErrorMessage,
curRegionData.preparingRegionId);
curRegionData.preparingRegionId = 0;
}
if (!_curMap.MapData.IsRegionExist(curRegionData.fallbackRegionId))
{
errorMessage += string.Format(FallbackRegionErrorMessage,
curRegionData.fallbackRegionId);
curRegionData.fallbackRegionId = 0;
}
if (!_curMap.MapData.IsRegionExist(curRegionData.enemyFallbackRegionId))
{
errorMessage += string.Format(EnemyFallbackRegionErrorMessage,
curRegionData.enemyFallbackRegionId);
curRegionData.enemyFallbackRegionId = 0;
}
if (!_curMap.MapData.IsRegionExist(curRegionData.flagTargetRegionId))
{
errorMessage += string.Format(FlagTargetRegionErrorMessage,
curRegionData.flagTargetRegionId);
curRegionData.flagTargetRegionId = 0;
}
foreach (var protectEditor in currentProtectUnits)
{
if (protectEditor.protectUnitInfo.protectStartPoint == protectEditor.protectUnitInfo.protectTargetPoint ||
protectEditor.protectUnitInfo.protectTargetPoint < 0 ||
protectEditor.protectUnitInfo.protectStartPoint < 0)
{
errorMessage += string.Format(ProtectUnitInfoErrorMessage,
protectEditor.protectUnitInfo.id);
break;
}
}
if (!string.IsNullOrEmpty(errorMessage))
{
CustomPopUpWindow.PopUp(errorMessage + FixedMessage);
}
}
private void Awake()
{
SceneView.duringSceneGui += OnSceneGUI;
}
protected override void OnEnable()
{
TerrainTypeConfig.Load();
_npcObjectDic = new Dictionary<Vector2Int, GameObject>();
_showNpcInfos = new List<NPCEditorInfo>();
base.OnEnable();
}
protected override void OnDisable()
{
currWindow = null;
//MapEditorUtils.UnLoadMap(EditorMap.Instance);
//DestroyImmediate(GameObject.Find("Main Camera"));
DestroyNpcPrefab();
_npcObjectDic = null;
base.OnDisable();
}
protected override void OnDestroy()
{
base.OnDestroy();
if (_curMap != null)
_curMap.TerrainGridSystem.OnMouseClickOnGrid -= OnCellClick;
SaveCurrentLevel();
SceneView.duringSceneGui -= OnSceneGUI;
}
private bool banSaveLevelList = false;
private void OnCurrentLevelDataChanged()
{
Debug.Log($"{GetType()}.OnCurrentLevelDataChanged");
}
private const string descKey = "LevelDesc";
private const string nameKey = "LevelName";
private void LoadLevel(LevelData levelData)
{
DestroyNpcPrefab();
_npcObjectDic.Clear();
_showNpcInfos.Clear();
currentLevelData = levelData;
//加载地区信息
curRegionData = new RegionData();
curRegionData.preparingRegionId = currentLevelData.preparingRegionId;
curRegionData.fallbackRegionId = currentLevelData.fallbackRegionId;
curRegionData.enemyFallbackRegionId = currentLevelData.enemyFallbackRegionId;
curRegionData.preparingRegionToward = currentLevelData.preparingRegionToward;
curRegionData.pvpDefendRegionId = currentLevelData.pvpDefendRegionId;
curRegionData.pvpDefendToward = currentLevelData.pvpDefendToward;
//加载抗旗和占领
curRegionData.flagTargetRegionId = currentLevelData.flagTargetRegionId;
curRegionData.captureProgress = currentLevelData.captureProgress;
_mapManager = FindObjectOfType<MapManager>();
_curMap = _mapManager.Map;
_curMap.TerrainGridSystem.OnMouseClickOnGrid += OnCellClick;
var monsterConfigDic = EditorTableManager.instance.tables.Monster.DataMap;
//加载NPC到场景中
currentNpcInfo = new();
var index = 1;
foreach (var npcInfo in currentLevelData.npcInfos)
{
var npcEditor = new NPCEditorInfo(npcInfo, index);
currentNpcInfo.Add(npcEditor);
if (!monsterConfigDic.TryGetValue(npcInfo.id, out var monsterClassData))
{
DebugUtil.LogError("请检查配置,没有 {0} 的怪物类ID", npcInfo.id);
continue;
}
npcInfo.level = monsterClassData.MonsterLevel;
var npcObj = LoadNpcPrefab(npcInfo.id);
if (npcObj != null)
{
var setPos = _curMap.BlockPosition2WorldPosition(npcInfo.position);
var yaw = LevelUtils.SetCharaterToward(npcInfo.npcToward);
_npcObjectDic.Add(npcInfo.position, Instantiate(npcObj, setPos, Quaternion.Euler(0, yaw, 0)));
}
index++;
}
//加载护送对象
currentProtectUnits = new List<ProtectEditorInfo>();
foreach (var protectUnit in currentLevelData.protectUnitInfos)
{
currentProtectUnits.Add(new ProtectEditorInfo(protectUnit));
}
}
private void OnCellClick(TerrainGridSystem tgs, int cellindex, int buttonindex)
{
if (isEditingProtectUnit) DebugUtil.LogWarning("当前点击索引: {0}", cellindex);
if (!ResponseClickOnCell) return;
var clickPosition = _curMap.TGSCellIndex2BlockPosition(cellindex);
int leftButton = 0;
int rightButton = 1;
if (buttonindex != leftButton && buttonindex != rightButton)
return;
bool opTrue = buttonindex == leftButton;
if (isEditingPatrolInfo)
{
if (opTrue)
AddPatrolInfo(clickPosition);
else
RemovePatrolInfo(clickPosition);
}
else if (isEditingNpcPos)
{
if (opTrue)
ChangeNpcPos(clickPosition);
}
else if (isEditingNPC)
{
if (opTrue)
{
AddNPC(clickPosition);
}
else
{
RemoveNPC(clickPosition);
}
}
}
private void ChangeNpcPos(Vector2Int clickPosition)
{
var oldPos = _currEditingNPCInfo.position;
if (oldPos == clickPosition) return;
var newWorldPos = _curMap.BlockPosition2WorldPosition(clickPosition);
if (_npcObjectDic.TryGetValue(oldPos, out var npcObj))
{
npcObj.transform.position = newWorldPos;
_currEditingNPCInfo.position = clickPosition;
_npcObjectDic.Remove(oldPos);
_npcObjectDic.Add(clickPosition, npcObj);
DebugUtil.Log("怪物: [ {0} ] 移动到 [ {1} ]位置上", _currEditingNPCInfo.id, clickPosition);
}
}
private void AddNPC(Vector2Int clickPosition)
{
if (npcObject == null || curMonsterID == 0)
{
DebugUtil.LogError("请选择正确的NPC");
return;
}
_npcObjectDic ??= new Dictionary<Vector2Int, GameObject>();
if (_npcObjectDic.ContainsKey(clickPosition))
{
DebugUtil.LogError("该位置已有NPC存在请重新选");
return;
}
LevelData.NPCInfo npcInfo = new LevelData.NPCInfo
{
id = curMonsterID,
position = clickPosition
};
var monsterConfigDic = EditorTableManager.instance.tables.Monster.DataMap;
if (monsterConfigDic.TryGetValue(curMonsterID, out var monster))
{
npcInfo.level = monster.MonsterLevel;
}
else
{
DebugUtil.LogError("获取怪物[{0}]配置数据错误", curMonsterID);
}
currentNpcInfo.Add(new(npcInfo, currentNpcInfo.Count + 1));
var pos = _curMap.BlockPosition2WorldPosition(npcInfo.position);
_npcObjectDic.Add(npcInfo.position, Instantiate(npcObject, pos, npcObject.transform.rotation));
DebugUtil.Log("添加了怪物: [ {0} ] 到 [ {1} ]位置上, 其预制体为: {2}", npcInfo.id, npcInfo.position, npcObject.name);
}
private void RemoveNPC(Vector2Int clickPosition)
{
if (_npcObjectDic.TryGetValue(clickPosition, out var npcObj))
{
var npc = currentNpcInfo.FirstOrDefault(npc => npc.npcInfo.position == clickPosition);
if (npc != null)
{
currentNpcInfo.Remove(npc);
DebugUtil.Log("从[ {0} ]位置上移除了[{1}]NPC", clickPosition, npcObj.name);
DestroyImmediate(npcObj);
_npcObjectDic.Remove(clickPosition);
}
}
ReorderNpcID();
}
private void AddPatrolInfo(Vector2Int clickPosition)
{
_currEditingNPCInfo.patrolInfos.Add(new LevelData.PatrolInfo()
{
patrolPoint = clickPosition,
});
}
private void RemovePatrolInfo(Vector2Int clickPosition)
{
var index = _currEditingNPCInfo.patrolInfos.FindLastIndex(pInfo => pInfo.patrolPoint == clickPosition);
if (index >= 0)
_currEditingNPCInfo.patrolInfos.RemoveAt(index);
}
private void StartEditPatrolInfo(LevelData.NPCInfo npcInfo)
{
isEditingPatrolInfo = true;
_currEditingNPCInfo = npcInfo;
}
private void FinishEditPatrolInfo()
{
isEditingPatrolInfo = false;
_currEditingNPCInfo = null;
}
private void ReorderNpcID()
{
for (var i = 0; i < currentNpcInfo.Count; i++)
{
currentNpcInfo[i].id = i + 1;
}
}
private void ChangeNpcID(LevelData.NPCInfo npcInfo, int newMonsterID)
{
if (_npcObjectDic.TryGetValue(npcInfo.position, out var npcObj))
{
var newObj = LoadNpcPrefab(newMonsterID);
if (newObj != null)
{
npcInfo.id = newMonsterID;
_npcObjectDic[npcInfo.position] = Instantiate(newObj, npcObj.transform.position, npcObj.transform.rotation);
DestroyImmediate(npcObj);
DebugUtil.Log("位置上[ {0} ]的怪物ID改为: [ {1} ] ", npcInfo.position, npcInfo.id);
}
}
}
private GameObject LoadNpcPrefab(int monsterID)
{
GameObject obj = null;
var monsterCfg = EditorTableManager.instance.tables.Monster;
if (monsterCfg.DataMap.TryGetValue(monsterID, out var monster))
{
_curMonsterClassID = monster.MonsterClassID;
}
else
{
return null;
}
switch (monster.NpcType)
{
case ENpcType.ENEMY_VEHICLE:
{
var vehicleConfig = EditorTableManager.instance.tables.EnemyVehicleConfig;
if (vehicleConfig.DataMap.TryGetValue(_curMonsterClassID, out var vehicle))
{
var prefabPath = PathEx.GetVehicleGameModelPath(vehicle.ID);
obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
if (obj == null)
{
DebugUtil.LogError("请检查载具类: {0}的预制体路径是否存在,对应的完整路径: {1}", _curMonsterClassID, prefabPath);
}
}
else
{
DebugUtil.LogError("请检查载具类: {0}的配置是否存在", _curMonsterClassID);
}
return obj;
}
case ENpcType.ENEMY_CHARACTER:
{
var monsterClassCfg = EditorTableManager.instance.tables.MonsterClass;
if (monsterClassCfg.DataMap.TryGetValue(_curMonsterClassID, out var monsterClass))
{
var prefabPath = PathEx.GetCharacterFightModelPath(monsterClass.NameId);
obj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
if (obj == null)
{
DebugUtil.LogError("请检查怪物类: {0}的预制体路径是否存在,对应的完整路径: {1}", _curMonsterClassID, prefabPath);
}
}
else
{
DebugUtil.LogError("请检查怪物类: {0}的配置是否存在", _curMonsterClassID);
}
return obj;
}
default: return null;
}
}
private void DestroyNpcPrefab()
{
foreach (var npc in _npcObjectDic)
{
DestroyImmediate(npc.Value);
}
}
private void ChangeNpcToward(Vector2Int pos, LevelData.CharacterToward npcToward)
{
if (_npcObjectDic.TryGetValue(pos, out var npcObj))
{
var yaw = LevelUtils.SetCharaterToward(npcToward);
npcObj.transform.eulerAngles = new Vector3(0, yaw, 0);
}
}
protected override void OnGUI()
{
base.OnGUI();
if (_levelEditor == null || _mapManager == null || _mapManager.Map != _curMap ||
_levelEditor.LevelData != currentLevelData)
{
Debug.LogError("数据已变更,请重新打开关卡编辑器");
Close();
}
}
private void OnSceneGUI(SceneView sceneView)
{
DrawPatrolPath();
DrawNpcID();
}
private void DrawPatrolPath()
{
if (!isEditingPatrolInfo) return;
Vector3 lastWorldPos = Vector3.zero;
for (int i = 0; i < _currEditingNPCInfo.patrolInfos.Count; i++)
{
var gridPos = _currEditingNPCInfo.patrolInfos[i].patrolPoint;
var worldPos = _curMap.BlockPosition2WorldPosition(gridPos);
Handles.color = Color.blue;
Handles.DrawSolidDisc(worldPos, Vector3.up, 0.4f);
if (i > 0)
{
Handles.color = Color.yellow;
EditorUtil.DrawArrowInScene(lastWorldPos, worldPos, 0.5f);
}
//Handles.color = Color.black;
Handles.Label(worldPos, i.ToString());
lastWorldPos = worldPos;
}
}
private GUIStyle labelStyle;
private void DrawNpcID()
{
if (!isShowNpcID) return;
if (labelStyle == null)
{
labelStyle = new GUIStyle
{
fontSize = 38,
fontStyle = FontStyle.Bold,
normal =
{
textColor = Color.red
}
};
}
foreach (var npc in _showNpcInfos)
{
if (_npcObjectDic.TryGetValue(npc.npcInfo.position, out var npcObj))
{
Handles.Label(npcObj.transform.position, npc.id.ToString(), labelStyle);
}
}
}
}