using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using UnityEngine; using UnityEngine.UIElements; using UnityEngine.Networking; // 可序列化的连线数据 [System.Serializable] public class SerializableWireData { public List wires = new List(); public System.DateTime lastSaveTime; public int wireCount; public string sceneName; } // 连线连接数据序列化结构 [System.Serializable] public class SerializableWireConnectionData { public string startInterfaceName; public string endInterfaceName; public Vector3 startConnectionPointPosition; public Vector3 endConnectionPointPosition; public Vector3 startPoint; public Vector3 endPoint; public string wireName; public System.DateTime creationTime; // 圆柱体特定数据 public Vector3 cylinderScale; public Vector3 cylinderPosition; public Quaternion cylinderRotation; public float cylinderRadius; // 调试信息 public bool hasStartInterface; public bool hasEndInterface; public string debugInfo; public string wireType; // 新增:颜色数据 public float wireColorR = 1f; public float wireColorG = 1f; public float wireColorB = 1f; public float wireColorA = 1f; public bool hasCustomColor = false; // 新增:连接点样式数据 public float connectionPointScale = 0.1f; public float startPointColorR = 1f; public float startPointColorG = 1f; public float startPointColorB = 1f; public float endPointColorR = 1f; public float endPointColorG = 1f; public float endPointColorB = 1f; // 新增:接口头样式名称 public string startInterfaceStyleName = ""; public string endInterfaceStyleName = ""; } public class WireDataPersistence : MonoBehaviour { [Header("数据持久化设置")] public bool enableAutoSave = true; // 启用自动保存 public float autoSaveInterval = 30f; // 自动保存间隔(秒) public string saveFileName = "WireData.json"; // 保存文件名 public bool loadOnStart = true; // 启动时自动加载 public bool debugMode = true; // 调试模式 public bool saveOnWireChange = true; // 连线变化时立即保存 [Header("圆柱体连线设置")] public Material cylinderWireMaterial; // 圆柱体连线材质 public Color defaultWireColor = Color.white; // 默认连线颜色 [Header("连接点设置")] public Material defaultConnectionPointMaterial; // 默认连接点材质 public Color defaultStartPointColor = Color.green; // 默认起点颜色 public Color defaultEndPointColor = Color.red; // 默认终点颜色 [Header("接口头样式设置")] public List interfaceStylePrefabs = new List(); // 接口头样式预制体列表 public string defaultInterfaceStyleName = "Default"; // 默认接口头样式名称 [Header("调试工具")] public bool enableDebugging = true; // 启用调试工具 public KeyCode manualSaveKey = KeyCode.F5; // 手动保存快捷键 public KeyCode manualLoadKey = KeyCode.F9; // 手动加载快捷键 public KeyCode debugInfoKey = KeyCode.F11; // 调试信息快捷键 // 引用连线系统 private WireDrawingSystem wireSystem; private string saveFilePath; private float lastSaveTime; private bool isInitialized = false; private int lastWireCount = 0; void Start() { Initialize(); } void Update() { if (!isInitialized) return; // 处理快捷键 HandleHotkeys(); // 检查连线数量变化 if (saveOnWireChange) { CheckWireCountChange(); } // 自动保存检查 if (enableAutoSave && Time.time - lastSaveTime >= autoSaveInterval) { SaveWireData(); lastSaveTime = Time.time; } } /// /// 处理快捷键 /// private void HandleHotkeys() { if (Input.GetKeyDown(manualSaveKey)) { Debug.Log("手动保存触发"); SaveWireData(); } if (Input.GetKeyDown(manualLoadKey)) { Debug.Log("手动加载触发"); StartCoroutine(LoadWireDataCoroutine()); } if (Input.GetKeyDown(debugInfoKey)) { ShowDebugInfo(); } // 新增:堆叠系统验证快捷键 if (Input.GetKeyDown(KeyCode.F12)) { Debug.Log("验证堆叠系统"); ValidateStackingSystem(); } if (Input.GetKeyDown(KeyCode.F10)) { TestStackingLimit("chudian218"); } } /// /// 显示调试信息 /// private void ShowDebugInfo() { Debug.Log("=== 连线数据持久化调试信息 ==="); Debug.Log($"保存文件路径: {saveFilePath}"); // WebGL中不能使用File.Exists,所以跳过这个检查 #if !UNITY_WEBGL Debug.Log($"文件存在: {File.Exists(saveFilePath)}"); #endif Debug.Log($"当前连线数量: {GetCurrentWireCount()}"); Debug.Log($"上次保存连线数量: {lastWireCount}"); Debug.Log($"系统初始化: {isInitialized}"); Debug.Log($"连线系统引用: {wireSystem != null}"); // 在WebGL中,我们无法直接检查文件存在,但可以尝试加载 StartCoroutine(CheckFileExistsCoroutine()); } /// /// 检查文件是否存在的协程(WebGL兼容) /// private IEnumerator CheckFileExistsCoroutine() { #if UNITY_WEBGL yield return StartCoroutine(CheckWebGLFileExists()); #else CheckStandardFileExists(); #endif } /// /// WebGL平台检查文件存在 /// private IEnumerator CheckWebGLFileExists() { string webglFilePath = Path.Combine(Application.streamingAssetsPath, saveFileName); UnityWebRequest webRequest = UnityWebRequest.Get(webglFilePath); yield return webRequest.SendWebRequest(); if (webRequest.result == UnityWebRequest.Result.Success) { Debug.Log($"WebGL文件存在: {webglFilePath}"); // 尝试读取文件内容 string jsonData = webRequest.downloadHandler.text; if (!string.IsNullOrEmpty(jsonData)) { ProcessFileContent(jsonData); } } else { Debug.Log("WebGL中没有找到连线数据文件"); } } /// /// 标准平台检查文件存在 /// private void CheckStandardFileExists() { if (File.Exists(saveFilePath)) { try { string jsonData = File.ReadAllText(saveFilePath); ProcessFileContent(jsonData); } catch (System.Exception e) { Debug.LogError($"读取保存文件失败: {e.Message}"); } } } /// /// 处理文件内容(通用方法) /// private void ProcessFileContent(string jsonData) { try { SerializableWireData data = JsonUtility.FromJson(jsonData); Debug.Log($"保存文件中的连线数量: {data.wireCount}"); Debug.Log($"保存时间: {data.lastSaveTime}"); Debug.Log($"场景名称: {data.sceneName}"); Debug.Log($"实际保存的连线数据条数: {data.wires.Count}"); // 显示连线类型统计和颜色信息 var typeGroups = data.wires.GroupBy(w => w.wireType); foreach (var group in typeGroups) { Debug.Log($"连线类型 '{group.Key}': {group.Count()} 条"); } // 显示颜色信息 int coloredWires = data.wires.Count(w => w.hasCustomColor); Debug.Log($"有自定义颜色的连线: {coloredWires}/{data.wires.Count}"); // 显示接口头样式统计 var startStyleGroups = data.wires.GroupBy(w => w.startInterfaceStyleName); var endStyleGroups = data.wires.GroupBy(w => w.endInterfaceStyleName); Debug.Log("=== 起点接口头样式统计 ==="); foreach (var group in startStyleGroups) { Debug.Log($"起点样式 '{group.Key}': {group.Count()} 个"); } Debug.Log("=== 终点接口头样式统计 ==="); foreach (var group in endStyleGroups) { Debug.Log($"终点样式 '{group.Key}': {group.Count()} 个"); } } catch (System.Exception e) { Debug.LogError($"处理文件内容失败: {e.Message}"); } } /// /// 检查连线数量变化 /// private void CheckWireCountChange() { try { int currentWireCount = GetCurrentWireCount(); if (currentWireCount != lastWireCount) { if (debugMode) Debug.Log($"WireDataPersistence: 连线数量变化 {lastWireCount} -> {currentWireCount}, 触发保存"); SaveWireData(); lastWireCount = currentWireCount; } } catch (System.Exception e) { Debug.LogWarning($"WireDataPersistence: 检查连线数量变化失败: {e.Message}"); } } /// /// 获取当前连线数量 /// private int GetCurrentWireCount() { if (wireSystem == null) return 0; try { // 通过反射获取连线系统的私有字段 var allWiresField = typeof(WireDrawingSystem).GetField("allWires", BindingFlags.NonPublic | BindingFlags.Instance); if (allWiresField == null) { if (debugMode) Debug.LogError("无法找到 allWires 字段"); return 0; } List allWires = (List)allWiresField.GetValue(wireSystem); return allWires?.Count ?? 0; } catch (System.Exception e) { if (debugMode) Debug.LogError($"获取连线数量失败: {e.Message}"); return 0; } } /// /// 初始化数据持久化系统 /// public void Initialize() { if (isInitialized) return; // 获取连线系统引用 wireSystem = GetComponent(); if (wireSystem == null) { Debug.LogError("WireDataPersistence: 找不到 WireDrawingSystem 组件!"); return; } // 设置保存文件路径 saveFilePath = Path.Combine(Application.streamingAssetsPath, saveFileName); if (debugMode) Debug.Log($"WireDataPersistence: 数据保存路径: {saveFilePath}"); // 启动时加载数据 if (loadOnStart) { // 延迟一帧加载,确保所有组件已初始化 StartCoroutine(DelayedLoad()); } // 初始化连线计数 lastWireCount = GetCurrentWireCount(); lastSaveTime = Time.time; isInitialized = true; if (debugMode) Debug.Log("WireDataPersistence: 初始化完成"); } /// /// 延迟加载 /// private IEnumerator DelayedLoad() { yield return new WaitForEndOfFrame(); yield return LoadWireDataCoroutine(); } /// /// 保存连线数据到文件 /// public void SaveWireData() { if (!isInitialized || wireSystem == null) { Debug.LogWarning("WireDataPersistence: 系统未初始化,无法保存数据"); return; } try { // 通过反射获取连线系统的私有字段 var allWiresField = typeof(WireDrawingSystem).GetField("allWires", BindingFlags.NonPublic | BindingFlags.Instance); if (allWiresField == null) { Debug.LogError("WireDataPersistence: 无法访问连线系统的内部数据"); return; } List allWires = (List)allWiresField.GetValue(wireSystem); SerializableWireData data = new SerializableWireData(); data.lastSaveTime = System.DateTime.Now; data.wireCount = allWires?.Count ?? 0; data.sceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name; // 收集所有连线的数据 int savedCount = 0; if (allWires != null) { foreach (var wire in allWires) { if (wire != null) { SerializableWireConnectionData wireData = GetWireConnectionData(wire); if (wireData != null) { data.wires.Add(wireData); savedCount++; if (debugMode) Debug.Log($"成功保存连线数据: {wireData.wireName} (类型: {wireData.wireType}, 颜色: {wireData.hasCustomColor}, 起点样式: {wireData.startInterfaceStyleName}, 终点样式: {wireData.endInterfaceStyleName})"); } else { if (debugMode) Debug.LogWarning($"无法获取连线数据: {wire.name}"); } } } } string jsonData = JsonUtility.ToJson(data, true); // WebGL和非WebGL平台使用不同的保存方式 #if UNITY_WEBGL // 在WebGL中使用PlayerPrefs存储数据 PlayerPrefs.SetString("WireData", jsonData); PlayerPrefs.Save(); #else // 确保目录存在 string directory = Path.GetDirectoryName(saveFilePath); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } File.WriteAllText(saveFilePath, jsonData); #endif if (debugMode) { Debug.Log($"WireDataPersistence: 数据已保存: {savedCount}/{data.wireCount} 条连线"); Debug.Log($"保存文件大小: {jsonData.Length} 字符"); // 显示连线类型统计 var typeGroups = data.wires.GroupBy(w => w.wireType); foreach (var group in typeGroups) { Debug.Log($"保存的连线类型 '{group.Key}': {group.Count()} 条"); } // 显示颜色统计 int coloredWires = data.wires.Count(w => w.hasCustomColor); Debug.Log($"保存的有颜色连线: {coloredWires}/{data.wires.Count}"); // 显示接口头样式统计 var startStyleGroups = data.wires.GroupBy(w => w.startInterfaceStyleName); var endStyleGroups = data.wires.GroupBy(w => w.endInterfaceStyleName); Debug.Log("=== 保存的起点接口头样式 ==="); foreach (var group in startStyleGroups) { Debug.Log($"起点样式 '{group.Key}': {group.Count()} 个"); } Debug.Log("=== 保存的终点接口头样式 ==="); foreach (var group in endStyleGroups) { Debug.Log($"终点样式 '{group.Key}': {group.Count()} 个"); } } } catch (System.Exception e) { Debug.LogError($"WireDataPersistence: 保存数据失败: {e.Message}\n{e.StackTrace}"); } } /// /// 从文件加载连线数据 - 协程版本(WebGL兼容) /// public IEnumerator LoadWireDataCoroutine() { if (!isInitialized || wireSystem == null) { Debug.LogWarning("WireDataPersistence: 系统未初始化,无法加载数据"); yield break; } string jsonData = ""; #if UNITY_WEBGL // WebGL平台从PlayerPrefs加载数据 if (PlayerPrefs.HasKey("WireData")) { jsonData = PlayerPrefs.GetString("WireData"); } else { // 如果PlayerPrefs中没有数据,尝试从StreamingAssets加载 yield return StartCoroutine(LoadFromStreamingAssets(saveFileName, result => { jsonData = result; })); } #else // 非WebGL平台使用文件系统 if (!File.Exists(saveFilePath)) { if (debugMode) Debug.Log("WireDataPersistence: 没有找到连线数据文件"); yield break; } jsonData = File.ReadAllText(saveFilePath); #endif if (string.IsNullOrEmpty(jsonData)) { if (debugMode) Debug.Log("WireDataPersistence: 没有找到连线数据"); yield break; } // 处理加载的数据 yield return StartCoroutine(ProcessLoadedData(jsonData)); } /// /// 从StreamingAssets加载数据 /// private IEnumerator LoadFromStreamingAssets(string fileName, System.Action onComplete) { string filePath = Path.Combine(Application.streamingAssetsPath, fileName); UnityWebRequest webRequest = UnityWebRequest.Get(filePath); yield return webRequest.SendWebRequest(); if (webRequest.result == UnityWebRequest.Result.Success) { onComplete(webRequest.downloadHandler.text); } else { onComplete(""); if (debugMode) Debug.Log("WireDataPersistence: 没有找到连线数据文件"); } } /// /// 处理加载的数据 /// private IEnumerator ProcessLoadedData(string jsonData) { try { SerializableWireData data = JsonUtility.FromJson(jsonData); if (debugMode) { Debug.Log($"WireDataPersistence: 开始加载数据: {data.wires.Count} 条连线, 保存时间: {data.lastSaveTime}"); // 显示连线类型统计 var typeGroups = data.wires.GroupBy(w => w.wireType); foreach (var group in typeGroups) { Debug.Log($"要加载的连线类型 '{group.Key}': {group.Count()} 条"); } // 显示颜色统计 int coloredWires = data.wires.Count(w => w.hasCustomColor); Debug.Log($"要加载的有颜色连线: {coloredWires}/{data.wires.Count}"); // 显示接口头样式统计 var startStyleGroups = data.wires.GroupBy(w => w.startInterfaceStyleName); var endStyleGroups = data.wires.GroupBy(w => w.endInterfaceStyleName); Debug.Log("=== 要加载的起点接口头样式 ==="); foreach (var group in startStyleGroups) { Debug.Log($"起点样式 '{group.Key}': {group.Count()} 个"); } Debug.Log("=== 要加载的终点接口头样式 ==="); foreach (var group in endStyleGroups) { Debug.Log($"终点样式 '{group.Key}': {group.Count()} 个"); } } // 如果 wires 为空但 wireCount > 0,说明数据有问题 if (data.wires.Count == 0 && data.wireCount > 0) { Debug.LogError($"数据不一致: wireCount = {data.wireCount}, 但 wires 数组为空"); yield break; } // 调用连线系统的清除方法 var clearAllMethod = typeof(WireDrawingSystem).GetMethod("ClearAll", BindingFlags.Public | BindingFlags.Instance); if (clearAllMethod != null) { clearAllMethod.Invoke(wireSystem, null); } else { Debug.LogWarning("WireDataPersistence: 无法调用 WireDrawingSystem 的 ClearAll 方法"); // 尝试手动清除 ManualClearWires(); } // 重建连线 int reconstructedCount = 0; foreach (var wireData in data.wires) { if (ReconstructWire(wireData)) { reconstructedCount++; } // 每重建10条连线就等待一帧,避免卡顿 //if (reconstructedCount % 10 == 0) //{ // yield return null; //} } if (debugMode) Debug.Log($"WireDataPersistence: 数据加载完成: {reconstructedCount}/{data.wires.Count} 条连线已恢复"); // 更新连线计数 lastWireCount = GetCurrentWireCount(); // 新增:验证堆叠系统 ValidateStackingSystem(); } catch (System.Exception e) { Debug.LogError($"WireDataPersistence: 加载数据失败: {e.Message}\n{e.StackTrace}"); } } /// /// 保持向后兼容的LoadWireData方法 /// public void LoadWireData() { StartCoroutine(LoadWireDataCoroutine()); } /// /// 手动清除连线(备用方法) /// private void ManualClearWires() { try { var allWiresField = typeof(WireDrawingSystem).GetField("allWires", BindingFlags.NonPublic | BindingFlags.Instance); var allConnectionPointsField = typeof(WireDrawingSystem).GetField("allConnectionPoints", BindingFlags.NonPublic | BindingFlags.Instance); if (allWiresField != null) { List allWires = (List)allWiresField.GetValue(wireSystem); if (allWires != null) { foreach (var wire in allWires.ToList()) { if (wire != null) DestroyImmediate(wire); } allWires.Clear(); } } if (allConnectionPointsField != null) { List allConnectionPoints = (List)allConnectionPointsField.GetValue(wireSystem); if (allConnectionPoints != null) { foreach (var point in allConnectionPoints.ToList()) { if (point != null) DestroyImmediate(point); } allConnectionPoints.Clear(); } } Debug.Log("手动清除连线完成"); } catch (System.Exception e) { Debug.LogError($"手动清除连线失败: {e.Message}"); } } /// /// 根据保存的数据重建连线 /// private bool ReconstructWire(SerializableWireConnectionData wireData) { try { if (debugMode) Debug.Log($"开始重建连线: {wireData.wireName} (类型: {wireData.wireType}, 颜色: {wireData.hasCustomColor}, 起点样式: {wireData.startInterfaceStyleName}, 终点样式: {wireData.endInterfaceStyleName})"); // 查找接口物体 GameObject startInterface = FindInterfaceByName(wireData.startInterfaceName); GameObject endInterface = FindInterfaceByName(wireData.endInterfaceName); // 如果接口不存在,记录警告但继续重建(使用null接口) if (startInterface == null && !string.IsNullOrEmpty(wireData.startInterfaceName)) { Debug.LogWarning($"无法找到起点接口: {wireData.startInterfaceName},将创建无接口连接"); } if (endInterface == null && !string.IsNullOrEmpty(wireData.endInterfaceName)) { Debug.LogWarning($"无法找到终点接口: {wireData.endInterfaceName},将创建无接口连接"); } if (debugMode) { Debug.Log($"起点接口: {wireData.startInterfaceName} -> {startInterface != null}"); Debug.Log($"终点接口: {wireData.endInterfaceName} -> {endInterface != null}"); Debug.Log($"起点接口头样式: {wireData.startInterfaceStyleName}"); Debug.Log($"终点接口头样式: {wireData.endInterfaceStyleName}"); } // 根据连线类型重建 if (wireData.wireType == "CylinderWireData") { return ReconstructCylinderWire(wireData, startInterface, endInterface); } else { // 默认使用圆柱体连线 return ReconstructCylinderWire(wireData, startInterface, endInterface); } } catch (System.Exception e) { Debug.LogError($"WireDataPersistence: 重建连线失败: {e.Message}\n{e.StackTrace}"); return false; } } /// /// 重建圆柱体连线 - 使用保存的圆柱体数据和接口头样式 /// private bool ReconstructCylinderWire(SerializableWireConnectionData wireData, GameObject startInterface, GameObject endInterface) { try { if (debugMode) Debug.Log($"重建圆柱体连线: {wireData.wireName}"); // 创建连线对象 GameObject wireObject = new GameObject(wireData.wireName); // 首先创建连接点,因为 CylinderWireData 可能需要引用它们 List connectionPoints = CreateConnectionPointsForWire(wireObject, wireData, startInterface, endInterface); // 添加 CylinderWireData 组件 CylinderWireData cylinderData = wireObject.AddComponent(); // 使用保存的连接点对象(如果有的话) GameObject startConnectionPoint = connectionPoints.Find(p => p.name.Contains("Start")); GameObject endConnectionPoint = connectionPoints.Find(p => p.name.Contains("End")); // 创建圆柱体视觉表现 - 使用保存的圆柱体数据 CreateCylinderVisual(wireObject, wireData); // 使用反射设置 CylinderWireData 的所有字段 SetCylinderWireDataFields(cylinderData, wireData, startInterface, endInterface); // 特别设置连接点引用(如果 CylinderWireData 需要它们) SetConnectionPointReferences(cylinderData, startConnectionPoint, endConnectionPoint); // 创建接口头样式 CreateInterfaceHeads(wireObject, wireData, startInterface, endInterface); // 添加到连线系统 AddWireToSystem(wireObject, wireData, startInterface, endInterface); // 注册连接点到堆叠系统 RegisterConnectionPointsToStackSystem(wireObject, startInterface, endInterface); if (debugMode) { Debug.Log($"WireDataPersistence: 成功重建圆柱体连线: {wireData.wireName}"); Debug.Log($"圆柱体缩放: {wireData.cylinderScale}, 位置: {wireData.cylinderPosition}"); Debug.Log($"连线颜色: {wireData.hasCustomColor}"); Debug.Log($"接口头样式 - 起点: {wireData.startInterfaceStyleName}, 终点: {wireData.endInterfaceStyleName}"); // 验证 CylinderWireData 字段是否设置正确 ValidateCylinderWireData(cylinderData); } return true; } catch (System.Exception e) { Debug.LogError($"重建圆柱体连线失败: {e.Message}"); return false; } } /// /// 创建接口头样式 /// private void CreateInterfaceHeads(GameObject wireObject, SerializableWireConnectionData wireData, GameObject startInterface, GameObject endInterface) { try { // 创建起点接口头 if (!string.IsNullOrEmpty(wireData.startInterfaceStyleName) && startInterface != null) { GameObject startHeadPrefab = GetInterfaceHeadPrefab(wireData.startInterfaceStyleName); if (startHeadPrefab != null) { GameObject startHead = Instantiate(startHeadPrefab); startHead.name = $"InterfaceHead_Start_{wireData.startInterfaceStyleName}"; startHead.transform.SetParent(wireObject.transform); // 设置接口头位置到起点接口位置 startHead.transform.position = startInterface.transform.position; startHead.transform.rotation = startInterface.transform.rotation; if (debugMode) Debug.Log($"创建起点接口头: {wireData.startInterfaceStyleName} 在 {startInterface.name}"); } else { Debug.LogWarning($"找不到起点接口头预制体: {wireData.startInterfaceStyleName}"); } } // 创建终点接口头 if (!string.IsNullOrEmpty(wireData.endInterfaceStyleName) && endInterface != null) { GameObject endHeadPrefab = GetInterfaceHeadPrefab(wireData.endInterfaceStyleName); if (endHeadPrefab != null) { GameObject endHead = Instantiate(endHeadPrefab); endHead.name = $"InterfaceHead_End_{wireData.endInterfaceStyleName}"; endHead.transform.SetParent(wireObject.transform); // 设置接口头位置到终点接口位置 endHead.transform.position = endInterface.transform.position; endHead.transform.rotation = endInterface.transform.rotation; if (debugMode) Debug.Log($"创建终点接口头: {wireData.endInterfaceStyleName} 在 {endInterface.name}"); } else { Debug.LogWarning($"找不到终点接口头预制体: {wireData.endInterfaceStyleName}"); } } } catch (System.Exception e) { Debug.LogError($"创建接口头失败: {e.Message}"); } } /// /// 根据样式名称获取接口头预制体 /// private GameObject GetInterfaceHeadPrefab(string styleName) { if (string.IsNullOrEmpty(styleName)) return null; foreach (GameObject prefab in interfaceStylePrefabs) { if (prefab != null && prefab.name == styleName) { return prefab; } } // 如果找不到指定名称的预制体,尝试使用默认样式 foreach (GameObject prefab in interfaceStylePrefabs) { if (prefab != null && prefab.name == defaultInterfaceStyleName) { return prefab; } } return null; } /// /// 设置连接点引用 /// private void SetConnectionPointReferences(CylinderWireData cylinderData, GameObject startPoint, GameObject endPoint) { try { FieldInfo[] fields = typeof(CylinderWireData).GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo field in fields) { try { if (field.FieldType == typeof(GameObject)) { if (field.Name.ToLower().Contains("start") && field.Name.ToLower().Contains("point")) { field.SetValue(cylinderData, startPoint); if (debugMode) Debug.Log($"设置起点连接点引用: {startPoint?.name ?? "null"}"); } else if (field.Name.ToLower().Contains("end") && field.Name.ToLower().Contains("point")) { field.SetValue(cylinderData, endPoint); if (debugMode) Debug.Log($"设置终点连接点引用: {endPoint?.name ?? "null"}"); } } } catch (System.Exception e) { Debug.LogWarning($"设置连接点引用 {field.Name} 失败: {e.Message}"); } } } catch (System.Exception e) { Debug.LogError($"设置连接点引用失败: {e.Message}"); } } /// /// 验证 CylinderWireData 字段设置 /// private void ValidateCylinderWireData(CylinderWireData cylinderData) { try { FieldInfo[] fields = typeof(CylinderWireData).GetFields(BindingFlags.Public | BindingFlags.Instance); Debug.Log("=== CylinderWireData 字段验证 ==="); foreach (FieldInfo field in fields) { object value = field.GetValue(cylinderData); Debug.Log($"{field.Name}: {value ?? "null"} (类型: {field.FieldType})"); } Debug.Log("=== 验证结束 ==="); } catch (System.Exception e) { Debug.LogError($"验证 CylinderWireData 失败: {e.Message}"); } } /// /// 注册连接点到堆叠系统 - 增强版 /// private void RegisterConnectionPointsToStackSystem(GameObject wireObject, GameObject startInterface, GameObject endInterface) { try { if (wireSystem == null) { if (debugMode) Debug.LogWarning("WireSystem 为 null,无法注册连接点到堆叠系统"); return; } // 获取 WireDrawingSystem 中的 interfaceStacks 字典 var interfaceStacksField = typeof(WireDrawingSystem).GetField("interfaceStacks", BindingFlags.NonPublic | BindingFlags.Instance); if (interfaceStacksField == null) { if (debugMode) Debug.LogWarning("无法找到 interfaceStacks 字段"); return; } var interfaceStacks = (Dictionary>)interfaceStacksField.GetValue(wireSystem); // 获取 allConnectionPoints 列表 var allConnectionPointsField = typeof(WireDrawingSystem).GetField("allConnectionPoints", BindingFlags.NonPublic | BindingFlags.Instance); List allConnectionPoints = null; if (allConnectionPointsField != null) { allConnectionPoints = (List)allConnectionPointsField.GetValue(wireSystem); } // 查找连线对象下的连接点并注册 int registeredCount = 0; foreach (Transform child in wireObject.transform) { if (child.name.StartsWith("ConnectionPoint_Start")) { // 只有当起点接口存在时才注册到堆叠系统 if (startInterface != null) { RegisterConnectionPointWithInterface(interfaceStacks, child.gameObject, startInterface); // 同时添加到 allConnectionPoints 列表 if (allConnectionPoints != null && !allConnectionPoints.Contains(child.gameObject)) { allConnectionPoints.Add(child.gameObject); } registeredCount++; } else if (debugMode) { Debug.Log($"起点接口为 null,跳过堆叠注册: {child.name}"); } } else if (child.name.StartsWith("ConnectionPoint_End")) { // 只有当终点接口存在时才注册到堆叠系统 if (endInterface != null) { RegisterConnectionPointWithInterface(interfaceStacks, child.gameObject, endInterface); // 同时添加到 allConnectionPoints 列表 if (allConnectionPoints != null && !allConnectionPoints.Contains(child.gameObject)) { allConnectionPoints.Add(child.gameObject); } registeredCount++; } else if (debugMode) { Debug.Log($"终点接口为 null,跳过堆叠注册: {child.name}"); } } } if (debugMode) { int startCount = startInterface != null ? GetStackCountForInterface(interfaceStacks, startInterface) : 0; int endCount = endInterface != null ? GetStackCountForInterface(interfaceStacks, endInterface) : 0; Debug.Log($"连接点堆叠注册完成 - 注册了 {registeredCount} 个连接点"); Debug.Log($"起点接口: {startInterface?.name ?? "null"} ({startCount}个), 终点接口: {endInterface?.name ?? "null"} ({endCount}个)"); Debug.Log($"allConnectionPoints 列表总数: {allConnectionPoints?.Count ?? 0}"); // 打印所有接口的堆叠状态 Debug.Log("=== 所有接口堆叠状态 ==="); foreach (var kvp in interfaceStacks) { Debug.Log($"接口: {kvp.Key}, 连接点数量: {kvp.Value.Count}"); } Debug.Log("=== 堆叠状态结束 ==="); } } catch (System.Exception e) { Debug.LogError($"注册连接点到堆叠系统失败: {e.Message}"); } } /// /// 验证堆叠限制是否正常工作 /// public void ValidateStackingSystem() { if (wireSystem == null) { Debug.LogError("WireSystem 为 null,无法验证堆叠系统"); return; } try { // 获取 WireDrawingSystem 中的 interfaceStacks 字典 var interfaceStacksField = typeof(WireDrawingSystem).GetField("interfaceStacks", BindingFlags.NonPublic | BindingFlags.Instance); if (interfaceStacksField == null) { Debug.LogError("无法找到 interfaceStacks 字段"); return; } var interfaceStacks = (Dictionary>)interfaceStacksField.GetValue(wireSystem); // 获取最大堆叠数量 var maxStackCountField = typeof(WireDrawingSystem).GetField("maxStackCount", BindingFlags.Public | BindingFlags.Instance); int maxStackCount = maxStackCountField != null ? (int)maxStackCountField.GetValue(wireSystem) : 5; Debug.Log("=== 堆叠系统验证 ==="); Debug.Log($"最大堆叠数量: {maxStackCount}"); Debug.Log($"接口数量: {interfaceStacks.Count}"); // 检查每个接口的堆叠状态 foreach (var kvp in interfaceStacks) { string interfaceObj = kvp.Key; List connectionPoints = kvp.Value; // 清理已销毁的连接点 connectionPoints.RemoveAll(item => item == null); Debug.Log($"接口: {interfaceObj}, 连接点数量: {connectionPoints.Count}, 是否达到限制: {connectionPoints.Count >= maxStackCount}"); // 验证每个连接点是否都有正确的引用 foreach (GameObject point in connectionPoints) { if (point != null) { ConnectionPointInterfaceReference refComponent = point.GetComponent(); if (refComponent == null || refComponent.targetInterface == null) { Debug.LogWarning($"连接点 {point.name} 缺少有效的接口引用"); } } } } Debug.Log("=== 验证结束 ==="); } catch (System.Exception e) { Debug.LogError($"验证堆叠系统失败: {e.Message}"); } } /// /// 注册单个连接点到接口堆叠系统 /// private void RegisterConnectionPointWithInterface(Dictionary> interfaceStacks, GameObject connectionPoint, GameObject targetInterface) { if (targetInterface == null) return; // 确保接口在字典中存在 if (!interfaceStacks.ContainsKey(targetInterface.name)) { interfaceStacks[targetInterface.name] = new List(); if (debugMode) Debug.Log($"为接口 {targetInterface.name} 创建新堆叠列表"); } // 添加连接点到堆叠列表 if (!interfaceStacks[targetInterface.name].Contains(connectionPoint)) { interfaceStacks[targetInterface.name].Add(connectionPoint); if (debugMode) Debug.Log($"连接点 {connectionPoint.name} 已注册到接口 {targetInterface.name},当前总数: {interfaceStacks[targetInterface.name].Count}"); } // 确保连接点有 ConnectionPointInterfaceReference 组件 ConnectionPointInterfaceReference refComponent = connectionPoint.GetComponent(); if (refComponent == null) { refComponent = connectionPoint.AddComponent(); } refComponent.targetInterface = targetInterface; } /// /// 获取接口上的连接点数量 /// private int GetStackCountForInterface(Dictionary> interfaceStacks, GameObject targetInterface) { if (targetInterface == null || !interfaceStacks.ContainsKey(targetInterface.name)) { return 0; } // 清理已销毁的模型引用 interfaceStacks[targetInterface.name].RemoveAll(item => item == null); return interfaceStacks[targetInterface.name].Count; } /// /// 使用反射设置 CylinderWireData 的所有字段 - 修复版 /// private void SetCylinderWireDataFields(CylinderWireData cylinderData, SerializableWireConnectionData wireData, GameObject startInterface, GameObject endInterface) { try { // 获取 CylinderWireData 类型的所有字段 FieldInfo[] fields = typeof(CylinderWireData).GetFields(BindingFlags.Public | BindingFlags.Instance); if (debugMode) Debug.Log($"CylinderWireData 有 {fields.Length} 个公共字段"); // 首先设置基本的连接点信息 foreach (FieldInfo field in fields) { try { // 根据字段名称设置对应的值 switch (field.Name) { case "startPoint": // 使用保存的起点位置 field.SetValue(cylinderData, wireData.startPoint); if (debugMode) Debug.Log($"设置 startPoint: {wireData.startPoint}"); break; case "endPoint": // 使用保存的终点位置 field.SetValue(cylinderData, wireData.endPoint); if (debugMode) Debug.Log($"设置 endPoint: {wireData.endPoint}"); break; case "snapStartObject": case "startInterface": // 设置起点接口 field.SetValue(cylinderData, startInterface); if (debugMode) Debug.Log($"设置 snapStartObject/startInterface: {startInterface?.name ?? "null"}"); break; case "snapEndObject": case "endInterface": // 设置终点接口 field.SetValue(cylinderData, endInterface); if (debugMode) Debug.Log($"设置 snapEndObject/endInterface: {endInterface?.name ?? "null"}"); break; case "creationTime": // 使用保存的创建时间 field.SetValue(cylinderData, wireData.creationTime); if (debugMode) Debug.Log($"设置 creationTime: {wireData.creationTime}"); break; case "wireDiameter": // 使用保存的圆柱体半径计算直径,或使用默认值 float diameter = wireData.cylinderRadius > 0 ? wireData.cylinderRadius * 2f : 0.02f; field.SetValue(cylinderData, diameter); if (debugMode) Debug.Log($"设置 wireDiameter: {diameter} (从半径 {wireData.cylinderRadius} 计算)"); break; default: // 尝试设置其他字段 if (debugMode) Debug.Log($"跳过字段: {field.Name} (类型: {field.FieldType})"); break; } } catch (System.Exception e) { Debug.LogWarning($"设置字段 {field.Name} 失败: {e.Message}"); } } // 额外设置一些可能需要的属性 SetAdditionalCylinderWireProperties(cylinderData, wireData); } catch (System.Exception e) { Debug.LogError($"设置 CylinderWireData 字段失败: {e.Message}"); } } /// /// 设置额外的圆柱体连线属性 /// private void SetAdditionalCylinderWireProperties(CylinderWireData cylinderData, SerializableWireConnectionData wireData) { try { // 使用反射设置可能存在的其他属性 PropertyInfo[] properties = typeof(CylinderWireData).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo property in properties) { try { if (property.CanWrite) { switch (property.Name) { case "WireColor": // 如果有自定义颜色,设置连线颜色 if (wireData.hasCustomColor) { Color wireColor = new Color(wireData.wireColorR, wireData.wireColorG, wireData.wireColorB, wireData.wireColorA); property.SetValue(cylinderData, wireColor); if (debugMode) Debug.Log($"设置 WireColor: {wireColor}"); } break; // 可以根据需要添加更多属性设置 } } } catch (System.Exception e) { Debug.LogWarning($"设置属性 {property.Name} 失败: {e.Message}"); } } } catch (System.Exception e) { Debug.LogError($"设置额外圆柱体连线属性失败: {e.Message}"); } } /// /// 创建圆柱体视觉表现 - 使用保存的圆柱体数据和颜色 /// private void CreateCylinderVisual(GameObject wireObject, SerializableWireConnectionData wireData) { try { // 创建圆柱体 GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder); if (cylinder == null) { Debug.LogError("创建圆柱体失败"); return; } cylinder.name = "WireCylinder"; cylinder.transform.SetParent(wireObject.transform); // 使用保存的圆柱体数据 if (wireData.cylinderScale != Vector3.zero) { // 使用保存的缩放 cylinder.transform.localScale = wireData.cylinderScale; if (debugMode) Debug.Log($"使用保存的圆柱体缩放: {wireData.cylinderScale}"); } else { // 计算连线的方向、距离和中点 Vector3 startPoint = wireData.startPoint; Vector3 endPoint = wireData.endPoint; Vector3 direction = (endPoint - startPoint).normalized; float distance = Vector3.Distance(startPoint, endPoint); Vector3 midpoint = (startPoint + endPoint) / 2; // 设置圆柱体的位置为中点 cylinder.transform.position = midpoint; // 计算正确的旋转 if (direction != Vector3.zero) { // 圆柱体默认朝向是Y轴,我们需要让它朝向连线方向 cylinder.transform.rotation = Quaternion.LookRotation(direction); // 圆柱体需要绕X轴旋转90度,因为圆柱体默认是立着的 cylinder.transform.Rotate(90, 0, 0, Space.Self); } // 设置圆柱体缩放 - 使用保存的半径或默认值 float radius = wireData.cylinderRadius > 0 ? wireData.cylinderRadius : 0.02f; cylinder.transform.localScale = new Vector3( radius, // X轴 - 半径 distance / 2, // Y轴 - 高度的一半(因为默认高度是2) radius // Z轴 - 半径 ); if (debugMode) Debug.Log($"使用计算的圆柱体缩放: {cylinder.transform.localScale}"); } // 使用保存的位置和旋转(如果存在) if (wireData.cylinderPosition != Vector3.zero) { cylinder.transform.position = wireData.cylinderPosition; if (debugMode) Debug.Log($"使用保存的圆柱体位置: {wireData.cylinderPosition}"); } if (wireData.cylinderRotation != Quaternion.identity) { cylinder.transform.rotation = wireData.cylinderRotation; if (debugMode) Debug.Log($"使用保存的圆柱体旋转: {wireData.cylinderRotation}"); } // 设置材质和颜色 Renderer renderer = cylinder.GetComponent(); if (renderer != null) { if (cylinderWireMaterial != null) { // 使用实例化材质以便单独设置颜色 Material wireMaterial = new Material(cylinderWireMaterial); // 如果保存了自定义颜色,使用保存的颜色;否则使用默认颜色 if (wireData.hasCustomColor) { Color savedColor = new Color( wireData.wireColorR, wireData.wireColorG, wireData.wireColorB, wireData.wireColorA ); wireMaterial.color = savedColor; if (debugMode) Debug.Log($"应用保存的连线颜色: {savedColor}"); } else { wireMaterial.color = defaultWireColor; if (debugMode) Debug.Log($"应用默认连线颜色: {defaultWireColor}"); } renderer.material = wireMaterial; } else { // 如果没有指定材质,直接设置颜色 if (wireData.hasCustomColor) { Color savedColor = new Color( wireData.wireColorR, wireData.wireColorG, wireData.wireColorB, wireData.wireColorA ); renderer.material.color = savedColor; } else { renderer.material.color = defaultWireColor; } } } // 移除碰撞器 Collider collider = cylinder.GetComponent(); if (collider != null) { DestroyImmediate(collider); } if (debugMode) Debug.Log($"圆柱体视觉创建完成: 位置={cylinder.transform.position}, 缩放={cylinder.transform.localScale}, 颜色={renderer.material.color}"); } catch (System.Exception e) { Debug.LogError($"创建圆柱体视觉失败: {e.Message}"); } } /// /// 为连线创建连接点 - 恢复连接点样式,返回创建的连接点列表 /// private List CreateConnectionPointsForWire(GameObject wireObject, SerializableWireConnectionData wireData, GameObject startInterface, GameObject endInterface) { List connectionPoints = new List(); try { // 通过反射获取连接点预制体 var connectionPointPrefabField = typeof(WireDrawingSystem).GetField("connectionPointPrefab", BindingFlags.Public | BindingFlags.Instance); GameObject connectionPointPrefab = connectionPointPrefabField != null ? (GameObject)connectionPointPrefabField.GetValue(wireSystem) : null; if (connectionPointPrefab != null) { // 创建起点连接点 if (wireData.startConnectionPointPosition != Vector3.zero) { GameObject startConnectionPoint = CreateConnectionPoint( wireData.startConnectionPointPosition, "ConnectionPoint_Start_Restored", connectionPointPrefab, wireData.connectionPointScale, new Color(wireData.startPointColorR, wireData.startPointColorG, wireData.startPointColorB), true ); if (startConnectionPoint != null) { startConnectionPoint.transform.SetParent(wireObject.transform); connectionPoints.Add(startConnectionPoint); } } // 创建终点连接点 if (wireData.endConnectionPointPosition != Vector3.zero) { GameObject endConnectionPoint = CreateConnectionPoint( wireData.endConnectionPointPosition, "ConnectionPoint_End_Restored", connectionPointPrefab, wireData.connectionPointScale, new Color(wireData.endPointColorR, wireData.endPointColorG, wireData.endPointColorB), false ); if (endConnectionPoint != null) { endConnectionPoint.transform.SetParent(wireObject.transform); connectionPoints.Add(endConnectionPoint); } } } } catch (System.Exception e) { Debug.LogWarning($"创建连接点失败: {e.Message}"); } return connectionPoints; } /// /// 创建连接点 - 支持颜色和样式恢复 /// private GameObject CreateConnectionPoint(Vector3 position, string name, GameObject prefab, float scale, Color color, bool isStartPoint) { if (prefab == null) return null; GameObject connectionPoint = Instantiate(prefab); connectionPoint.name = name; connectionPoint.transform.position = position; // 设置缩放 try { connectionPoint.transform.localScale = Vector3.one * scale; if (debugMode) Debug.Log($"设置连接点缩放: {scale}"); } catch { connectionPoint.transform.localScale = Vector3.one * 0.1f; } // 设置材质和颜色 try { Renderer renderer = connectionPoint.GetComponent(); if (renderer != null) { if (defaultConnectionPointMaterial != null) { // 使用实例化材质以便单独设置颜色 Material pointMaterial = new Material(defaultConnectionPointMaterial); pointMaterial.color = color; renderer.material = pointMaterial; if (debugMode) Debug.Log($"应用连接点颜色: {color} ({(isStartPoint ? "起点" : "终点")})"); } else { // 直接设置材质颜色 renderer.material.color = color; } } } catch (System.Exception e) { Debug.LogWarning($"设置连接点材质失败: {e.Message}"); } return connectionPoint; } /// /// 将连线添加到连线系统 /// private void AddWireToSystem(GameObject wireObject, SerializableWireConnectionData wireData, GameObject startInterface, GameObject endInterface) { try { // 通过反射访问连线系统的内部列表 var allWiresField = typeof(WireDrawingSystem).GetField("allWires", BindingFlags.NonPublic | BindingFlags.Instance); var allConnectionPointsField = typeof(WireDrawingSystem).GetField("allConnectionPoints", BindingFlags.NonPublic | BindingFlags.Instance); if (allWiresField != null) { List allWires = (List)allWiresField.GetValue(wireSystem); if (allWires != null) { allWires.Add(wireObject); } } // 添加连接点到列表 if (allConnectionPointsField != null) { List allConnectionPoints = (List)allConnectionPointsField.GetValue(wireSystem); if (allConnectionPoints != null) { foreach (Transform child in wireObject.transform) { if (child.name.StartsWith("ConnectionPoint_")) { allConnectionPoints.Add(child.gameObject); } } } } if (debugMode) Debug.Log($"连线已添加到系统: {wireData.wireName}"); } catch (System.Exception e) { Debug.LogError($"添加连线到系统失败: {e.Message}"); } } /// /// 获取连线的连接数据 - 关键修复方法,保存圆柱体数据、颜色和接口头样式 /// private SerializableWireConnectionData GetWireConnectionData(GameObject wireObject) { try { if (wireObject == null) { if (debugMode) Debug.LogWarning("连线对象为 null"); return null; } // 方法1:首先尝试从 CylinderWireData 组件获取 CylinderWireData cylinderData = wireObject.GetComponent(); if (cylinderData != null) { SerializableWireConnectionData connectionData = new SerializableWireConnectionData { wireName = wireObject.name, creationTime = System.DateTime.Now, debugInfo = "从 CylinderWireData 组件获取", wireType = "CylinderWireData" }; // 使用反射获取所有字段 FieldInfo[] fields = typeof(CylinderWireData).GetFields(BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo field in fields) { try { switch (field.Name) { case "startPoint": connectionData.startPoint = (Vector3)field.GetValue(cylinderData); break; case "endPoint": connectionData.endPoint = (Vector3)field.GetValue(cylinderData); break; case "startInterface": GameObject startInterface = (GameObject)field.GetValue(cylinderData); connectionData.startInterfaceName = startInterface ? startInterface.name : ""; connectionData.hasStartInterface = startInterface != null; break; case "endInterface": GameObject endInterface = (GameObject)field.GetValue(cylinderData); connectionData.endInterfaceName = endInterface ? endInterface.name : ""; connectionData.hasEndInterface = endInterface != null; break; } } catch (System.Exception e) { Debug.LogWarning($"获取字段 {field.Name} 失败: {e.Message}"); } } // 查找圆柱体子物体并保存其数据和颜色 Transform cylinderChild = wireObject.transform.Find("WireCylinder"); if (cylinderChild != null) { connectionData.cylinderScale = cylinderChild.localScale; connectionData.cylinderPosition = cylinderChild.position; connectionData.cylinderRotation = cylinderChild.rotation; // 计算圆柱体半径(取X和Z缩放的平均值) connectionData.cylinderRadius = (cylinderChild.localScale.x + cylinderChild.localScale.z) / 2f; // 保存圆柱体颜色 Renderer cylinderRenderer = cylinderChild.GetComponent(); if (cylinderRenderer != null && cylinderRenderer.material != null) { Color wireColor = cylinderRenderer.material.color; connectionData.wireColorR = wireColor.r; connectionData.wireColorG = wireColor.g; connectionData.wireColorB = wireColor.b; connectionData.wireColorA = wireColor.a; connectionData.hasCustomColor = true; if (debugMode) Debug.Log($"保存连线颜色: {wireColor}"); } if (debugMode) { Debug.Log($"保存圆柱体数据: 缩放={connectionData.cylinderScale}, 位置={connectionData.cylinderPosition}, 半径={connectionData.cylinderRadius}"); } } // 查找连接点的位置、缩放和颜色 foreach (Transform child in wireObject.transform) { if (child.name.StartsWith("ConnectionPoint_Start")) { connectionData.startConnectionPointPosition = child.position; connectionData.connectionPointScale = child.localScale.x; // 假设均匀缩放 // 保存起点连接点颜色 Renderer startRenderer = child.GetComponent(); if (startRenderer != null && startRenderer.material != null) { Color startColor = startRenderer.material.color; connectionData.startPointColorR = startColor.r; connectionData.startPointColorG = startColor.g; connectionData.startPointColorB = startColor.b; } } else if (child.name.StartsWith("ConnectionPoint_End")) { connectionData.endConnectionPointPosition = child.position; // 保存终点连接点颜色 Renderer endRenderer = child.GetComponent(); if (endRenderer != null && endRenderer.material != null) { Color endColor = endRenderer.material.color; connectionData.endPointColorR = endColor.r; connectionData.endPointColorG = endColor.g; connectionData.endPointColorB = endColor.b; } } } // 查找接口头样式并保存 foreach (Transform child in wireObject.transform) { if (child.name.StartsWith("InterfaceHead_Start")) { // 从接口头名称中提取样式名称 string headName = child.name; if (headName.Contains("_")) { string[] parts = headName.Split('_'); if (parts.Length >= 3) { connectionData.startInterfaceStyleName = parts[2]; if (debugMode) Debug.Log($"保存起点接口头样式: {connectionData.startInterfaceStyleName}"); } } } else if (child.name.StartsWith("InterfaceHead_End")) { // 从接口头名称中提取样式名称 string headName = child.name; if (headName.Contains("_")) { string[] parts = headName.Split('_'); if (parts.Length >= 3) { connectionData.endInterfaceStyleName = parts[2]; if (debugMode) Debug.Log($"保存终点接口头样式: {connectionData.endInterfaceStyleName}"); } } } } if (debugMode) { Debug.Log($"从 CylinderWireData 组件获取连线数据: {connectionData.wireName}"); Debug.Log($"起点: {connectionData.startPoint}, 终点: {connectionData.endPoint}"); Debug.Log($"起点接口: {connectionData.startInterfaceName}, 终点接口: {connectionData.endInterfaceName}"); Debug.Log($"连线颜色: {connectionData.hasCustomColor}"); Debug.Log($"接口头样式 - 起点: {connectionData.startInterfaceStyleName}, 终点: {connectionData.endInterfaceStyleName}"); } return connectionData; } // 方法2:尝试从 WireData 组件获取(兼容旧版本) WireData wireDataComponent = wireObject.GetComponent(); if (wireDataComponent != null) { SerializableWireConnectionData connectionData = new SerializableWireConnectionData { startInterfaceName = wireDataComponent.snapStartObject ? wireDataComponent.snapStartObject.name : "", endInterfaceName = wireDataComponent.snapEndObject ? wireDataComponent.snapEndObject.name : "", startPoint = wireDataComponent.startPoint, endPoint = wireDataComponent.endPoint, wireName = wireObject.name, creationTime = wireDataComponent.creationTime, hasStartInterface = wireDataComponent.snapStartObject != null, hasEndInterface = wireDataComponent.snapEndObject != null, debugInfo = "从 WireData 组件获取", wireType = "WireData" }; // 查找连接点的位置、缩放和颜色 foreach (Transform child in wireObject.transform) { if (child.name.StartsWith("ConnectionPoint_Start")) { connectionData.startConnectionPointPosition = child.position; connectionData.connectionPointScale = child.localScale.x; Renderer startRenderer = child.GetComponent(); if (startRenderer != null && startRenderer.material != null) { Color startColor = startRenderer.material.color; connectionData.startPointColorR = startColor.r; connectionData.startPointColorG = startColor.g; connectionData.startPointColorB = startColor.b; } } else if (child.name.StartsWith("ConnectionPoint_End")) { connectionData.endConnectionPointPosition = child.position; Renderer endRenderer = child.GetComponent(); if (endRenderer != null && endRenderer.material != null) { Color endColor = endRenderer.material.color; connectionData.endPointColorR = endColor.r; connectionData.endPointColorG = endColor.g; connectionData.endPointColorB = endColor.b; } } } // 尝试获取连线颜色 Transform wireVisual = wireObject.transform.Find("WireCylinder"); if (wireVisual != null) { Renderer wireRenderer = wireVisual.GetComponent(); if (wireRenderer != null && wireRenderer.material != null) { Color wireColor = wireRenderer.material.color; connectionData.wireColorR = wireColor.r; connectionData.wireColorG = wireColor.g; connectionData.wireColorB = wireColor.b; connectionData.wireColorA = wireColor.a; connectionData.hasCustomColor = true; } } // 查找接口头样式并保存 foreach (Transform child in wireObject.transform) { if (child.name.StartsWith("InterfaceHead_Start")) { string headName = child.name; if (headName.Contains("_")) { string[] parts = headName.Split('_'); if (parts.Length >= 3) { connectionData.startInterfaceStyleName = parts[2]; } } } else if (child.name.StartsWith("InterfaceHead_End")) { string headName = child.name; if (headName.Contains("_")) { string[] parts = headName.Split('_'); if (parts.Length >= 3) { connectionData.endInterfaceStyleName = parts[2]; } } } } if (debugMode) Debug.Log($"从 WireData 组件获取连线数据: {connectionData.wireName}"); return connectionData; } if (debugMode) Debug.LogWarning($"无法获取连线数据: {wireObject.name},所有方法都失败"); return null; } catch (System.Exception e) { Debug.LogError($"获取连线数据失败: {e.Message}"); return null; } } /// /// 根据名称查找接口对象 - 增强查找能力 /// private GameObject FindInterfaceByName(string interfaceName) { if (string.IsNullOrEmpty(interfaceName)) { if (debugMode) Debug.LogWarning("接口名称为空"); return null; } // 方法1:直接通过名称查找 GameObject obj = GameObject.Find(interfaceName); if (obj != null) { if (debugMode) Debug.Log($"通过名称找到接口: {interfaceName}"); return obj; } // 方法2:在场景中查找包含该名称的对象 GameObject[] allObjects = GameObject.FindObjectsOfType(); foreach (GameObject gameObj in allObjects) { if (gameObj.name.Contains(interfaceName)) { if (debugMode) Debug.Log($"通过包含名称找到接口: {interfaceName} -> {gameObj.name}"); return gameObj; } } // 方法3:通过标签查找(如果有特定标签) try { GameObject[] taggedObjs = GameObject.FindGameObjectsWithTag("Interface"); foreach (GameObject taggedObj in taggedObjs) { if (taggedObj.name == interfaceName) { if (debugMode) Debug.Log($"通过标签找到接口: {interfaceName}"); return taggedObj; } } } catch { } if (debugMode) Debug.LogWarning($"WireDataPersistence: 找不到接口物体: {interfaceName}"); return null; } /// /// 手动保存 /// public void ManualSave() { SaveWireData(); } /// /// 手动加载 /// public void ManualLoad() { StartCoroutine(LoadWireDataCoroutine()); } /// /// 清除所有保存的数据 /// public void ClearSavedData() { #if UNITY_WEBGL // WebGL中使用PlayerPrefs if (PlayerPrefs.HasKey("WireData")) { PlayerPrefs.DeleteKey("WireData"); PlayerPrefs.Save(); if (debugMode) Debug.Log("WireDataPersistence: 已清除PlayerPrefs中的连线数据"); } #else if (File.Exists(saveFilePath)) { File.Delete(saveFilePath); if (debugMode) Debug.Log("WireDataPersistence: 已清除保存的数据文件"); } #endif } /// /// 获取保存信息 /// public string GetSaveInfo() { #if UNITY_WEBGL if (PlayerPrefs.HasKey("WireData")) { try { string jsonData = PlayerPrefs.GetString("WireData"); SerializableWireData data = JsonUtility.FromJson(jsonData); int coloredWires = data.wires.Count(w => w.hasCustomColor); // 统计接口头样式 var startStyleGroups = data.wires.GroupBy(w => w.startInterfaceStyleName); var endStyleGroups = data.wires.GroupBy(w => w.endInterfaceStyleName); string styleInfo = ""; foreach (var group in startStyleGroups) { if (!string.IsNullOrEmpty(group.Key)) styleInfo += $", 起点{group.Key}:{group.Count()}"; } foreach (var group in endStyleGroups) { if (!string.IsNullOrEmpty(group.Key)) styleInfo += $", 终点{group.Key}:{group.Count()}"; } return $"WireDataPersistence: 已保存 {data.wires.Count} 条连线 ({coloredWires} 条有颜色{styleInfo}), 文件大小: {jsonData.Length} 字符, 存储: PlayerPrefs"; } catch { return "WireDataPersistence: PlayerPrefs中存在数据但读取失败"; } } else { return "WireDataPersistence: PlayerPrefs中暂无保存数据"; } #else if (File.Exists(saveFilePath)) { FileInfo fileInfo = new FileInfo(saveFilePath); try { string jsonData = File.ReadAllText(saveFilePath); SerializableWireData data = JsonUtility.FromJson(jsonData); int coloredWires = data.wires.Count(w => w.hasCustomColor); // 统计接口头样式 var startStyleGroups = data.wires.GroupBy(w => w.startInterfaceStyleName); var endStyleGroups = data.wires.GroupBy(w => w.endInterfaceStyleName); string styleInfo = ""; foreach (var group in startStyleGroups) { if (!string.IsNullOrEmpty(group.Key)) styleInfo += $", 起点{group.Key}:{group.Count()}"; } foreach (var group in endStyleGroups) { if (!string.IsNullOrEmpty(group.Key)) styleInfo += $", 终点{group.Key}:{group.Count()}"; } return $"WireDataPersistence: 已保存 {data.wires.Count} 条连线 ({coloredWires} 条有颜色{styleInfo}), 文件大小: {fileInfo.Length} 字节, 路径: {saveFilePath}"; } catch { return $"WireDataPersistence: 文件存在但读取失败, 大小: {fileInfo.Length} 字节"; } } else { return "WireDataPersistence: 暂无保存数据"; } #endif } /// /// 检查是否有保存的数据 /// public bool HasSavedData() { #if UNITY_WEBGL return PlayerPrefs.HasKey("WireData"); #else return File.Exists(saveFilePath); #endif } /// /// 获取保存文件路径 /// public string GetSaveFilePath() { return saveFilePath; } /// /// 获取当前连线的统计信息 /// public string GetWireStats() { if (!isInitialized || wireSystem == null) return "系统未初始化"; try { var allWiresField = typeof(WireDrawingSystem).GetField("allWires", BindingFlags.NonPublic | BindingFlags.Instance); if (allWiresField == null) return "无法访问连线数据"; List allWires = (List)allWiresField.GetValue(wireSystem); // 统计连线类型 int cylinderCount = 0; int lineRendererCount = 0; int unknownCount = 0; int coloredWires = 0; // 统计接口头样式 Dictionary startInterfaceStyles = new Dictionary(); Dictionary endInterfaceStyles = new Dictionary(); if (allWires != null) { foreach (var wire in allWires) { if (wire != null) { if (wire.GetComponent() != null) cylinderCount++; else if (wire.GetComponent() != null) lineRendererCount++; else unknownCount++; // 检查是否有自定义颜色 Transform cylinder = wire.transform.Find("WireCylinder"); if (cylinder != null) { Renderer renderer = cylinder.GetComponent(); if (renderer != null && renderer.material != null && renderer.material.color != defaultWireColor) { coloredWires++; } } // 统计接口头样式 foreach (Transform child in wire.transform) { if (child.name.StartsWith("InterfaceHead_Start")) { string styleName = ExtractStyleNameFromHead(child.name); if (!string.IsNullOrEmpty(styleName)) { if (startInterfaceStyles.ContainsKey(styleName)) startInterfaceStyles[styleName]++; else startInterfaceStyles[styleName] = 1; } } else if (child.name.StartsWith("InterfaceHead_End")) { string styleName = ExtractStyleNameFromHead(child.name); if (!string.IsNullOrEmpty(styleName)) { if (endInterfaceStyles.ContainsKey(styleName)) endInterfaceStyles[styleName]++; else endInterfaceStyles[styleName] = 1; } } } } } } string styleStats = ""; foreach (var kvp in startInterfaceStyles) { styleStats += $", 起点{kvp.Key}:{kvp.Value}"; } foreach (var kvp in endInterfaceStyles) { styleStats += $", 终点{kvp.Key}:{kvp.Value}"; } return $"当前场景中有 {allWires?.Count ?? 0} 条连线 (圆柱体: {cylinderCount}, LineRenderer: {lineRendererCount}, 未知: {unknownCount}, 有颜色: {coloredWires}{styleStats})"; } catch (System.Exception e) { return $"获取统计信息失败: {e.Message}"; } } /// /// 从接口头名称中提取样式名称 /// private string ExtractStyleNameFromHead(string headName) { if (string.IsNullOrEmpty(headName)) return ""; if (headName.Contains("_")) { string[] parts = headName.Split('_'); if (parts.Length >= 3) { return parts[2]; } } return ""; } /// /// 测试特定接口的堆叠限制 /// public void TestStackingLimit(string interfaceName) { if (wireSystem == null) { Debug.LogError("WireSystem 为 null,无法测试堆叠限制"); return; } try { // 获取 WireDrawingSystem 中的 interfaceStacks 字典 var interfaceStacksField = typeof(WireDrawingSystem).GetField("interfaceStacks", BindingFlags.NonPublic | BindingFlags.Instance); if (interfaceStacksField == null) { Debug.LogError("无法找到 interfaceStacks 字段"); return; } var interfaceStacks = (Dictionary>)interfaceStacksField.GetValue(wireSystem); // 查找接口 GameObject targetInterface = null; foreach (var kvp in interfaceStacks) { if (kvp.Key.name == interfaceName) { targetInterface = kvp.Key; break; } } if (targetInterface == null) { Debug.LogWarning($"找不到接口: {interfaceName}"); return; } // 获取堆叠检查方法 var isStackLimitReachedMethod = typeof(WireDrawingSystem).GetMethod("IsStackLimitReached", BindingFlags.NonPublic | BindingFlags.Instance); if (isStackLimitReachedMethod == null) { Debug.LogError("无法找到 IsStackLimitReached 方法"); return; } bool isLimitReached = (bool)isStackLimitReachedMethod.Invoke(wireSystem, new object[] { targetInterface }); Debug.Log($"堆叠限制测试 - 接口: {interfaceName}, 是否达到限制: {isLimitReached}"); } catch (System.Exception e) { Debug.LogError($"测试堆叠限制失败: {e.Message}"); } } /// /// 强制立即保存 /// public void ForceSave() { SaveWireData(); } }