1150 lines
39 KiB
C#
1150 lines
39 KiB
C#
using UnityEngine;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
|
||
// 可序列化的连线数据
|
||
[System.Serializable]
|
||
public class SerializableWireData
|
||
{
|
||
public List<SerializableWireConnectionData> wires = new List<SerializableWireConnectionData>();
|
||
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 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; // 圆柱体连线材质
|
||
|
||
[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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理快捷键
|
||
/// </summary>
|
||
private void HandleHotkeys()
|
||
{
|
||
if (Input.GetKeyDown(manualSaveKey))
|
||
{
|
||
Debug.Log("手动保存触发");
|
||
SaveWireData();
|
||
}
|
||
|
||
if (Input.GetKeyDown(manualLoadKey))
|
||
{
|
||
Debug.Log("手动加载触发");
|
||
LoadWireData();
|
||
}
|
||
|
||
if (Input.GetKeyDown(debugInfoKey))
|
||
{
|
||
ShowDebugInfo();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示调试信息
|
||
/// </summary>
|
||
private void ShowDebugInfo()
|
||
{
|
||
Debug.Log("=== 连线数据持久化调试信息 ===");
|
||
Debug.Log($"保存文件路径: {saveFilePath}");
|
||
Debug.Log($"文件存在: {File.Exists(saveFilePath)}");
|
||
Debug.Log($"当前连线数量: {GetCurrentWireCount()}");
|
||
Debug.Log($"上次保存连线数量: {lastWireCount}");
|
||
Debug.Log($"系统初始化: {isInitialized}");
|
||
Debug.Log($"连线系统引用: {wireSystem != null}");
|
||
|
||
if (File.Exists(saveFilePath))
|
||
{
|
||
try
|
||
{
|
||
string jsonData = File.ReadAllText(saveFilePath);
|
||
SerializableWireData data = JsonUtility.FromJson<SerializableWireData>(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()} 条");
|
||
}
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogError($"读取保存文件失败: {e.Message}");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查连线数量变化
|
||
/// </summary>
|
||
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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前连线数量
|
||
/// </summary>
|
||
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<GameObject> allWires = (List<GameObject>)allWiresField.GetValue(wireSystem);
|
||
return allWires?.Count ?? 0;
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
if (debugMode) Debug.LogError($"获取连线数量失败: {e.Message}");
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化数据持久化系统
|
||
/// </summary>
|
||
public void Initialize()
|
||
{
|
||
if (isInitialized) return;
|
||
|
||
// 获取连线系统引用
|
||
wireSystem = GetComponent<WireDrawingSystem>();
|
||
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: 初始化完成");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 延迟加载
|
||
/// </summary>
|
||
private IEnumerator DelayedLoad()
|
||
{
|
||
yield return new WaitForEndOfFrame();
|
||
LoadWireData();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存连线数据到文件
|
||
/// </summary>
|
||
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<GameObject> allWires = (List<GameObject>)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})");
|
||
}
|
||
else
|
||
{
|
||
if (debugMode) Debug.LogWarning($"无法获取连线数据: {wire.name}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
string jsonData = JsonUtility.ToJson(data, true);
|
||
|
||
// 确保目录存在
|
||
string directory = Path.GetDirectoryName(saveFilePath);
|
||
if (!Directory.Exists(directory))
|
||
{
|
||
Directory.CreateDirectory(directory);
|
||
}
|
||
|
||
File.WriteAllText(saveFilePath, jsonData);
|
||
|
||
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()} 条");
|
||
}
|
||
}
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogError($"WireDataPersistence: 保存数据失败: {e.Message}\n{e.StackTrace}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从文件加载连线数据
|
||
/// </summary>
|
||
public void LoadWireData()
|
||
{
|
||
if (!isInitialized || wireSystem == null)
|
||
{
|
||
Debug.LogWarning("WireDataPersistence: 系统未初始化,无法加载数据");
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
if (!File.Exists(saveFilePath))
|
||
{
|
||
if (debugMode) Debug.Log("WireDataPersistence: 没有找到连线数据文件");
|
||
return;
|
||
}
|
||
|
||
string jsonData = File.ReadAllText(saveFilePath);
|
||
if (string.IsNullOrEmpty(jsonData))
|
||
{
|
||
Debug.LogError("WireDataPersistence: 保存文件为空");
|
||
return;
|
||
}
|
||
|
||
SerializableWireData data = JsonUtility.FromJson<SerializableWireData>(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()} 条");
|
||
}
|
||
}
|
||
|
||
// 如果 wires 为空但 wireCount > 0,说明数据有问题
|
||
if (data.wires.Count == 0 && data.wireCount > 0)
|
||
{
|
||
Debug.LogError($"数据不一致: wireCount = {data.wireCount}, 但 wires 数组为空");
|
||
return;
|
||
}
|
||
|
||
// 调用连线系统的清除方法
|
||
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++;
|
||
}
|
||
}
|
||
|
||
if (debugMode) Debug.Log($"WireDataPersistence: 数据加载完成: {reconstructedCount}/{data.wires.Count} 条连线已恢复");
|
||
|
||
// 更新连线计数
|
||
lastWireCount = GetCurrentWireCount();
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogError($"WireDataPersistence: 加载数据失败: {e.Message}\n{e.StackTrace}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 手动清除连线(备用方法)
|
||
/// </summary>
|
||
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<GameObject> allWires = (List<GameObject>)allWiresField.GetValue(wireSystem);
|
||
if (allWires != null)
|
||
{
|
||
foreach (var wire in allWires.ToList())
|
||
{
|
||
if (wire != null) DestroyImmediate(wire);
|
||
}
|
||
allWires.Clear();
|
||
}
|
||
}
|
||
|
||
if (allConnectionPointsField != null)
|
||
{
|
||
List<GameObject> allConnectionPoints = (List<GameObject>)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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据保存的数据重建连线
|
||
/// </summary>
|
||
private bool ReconstructWire(SerializableWireConnectionData wireData)
|
||
{
|
||
try
|
||
{
|
||
if (debugMode) Debug.Log($"开始重建连线: {wireData.wireName} (类型: {wireData.wireType})");
|
||
|
||
// 查找接口物体
|
||
GameObject startInterface = FindInterfaceByName(wireData.startInterfaceName);
|
||
GameObject endInterface = FindInterfaceByName(wireData.endInterfaceName);
|
||
|
||
if (debugMode)
|
||
{
|
||
Debug.Log($"起点接口: {wireData.startInterfaceName} -> {startInterface != null}");
|
||
Debug.Log($"终点接口: {wireData.endInterfaceName} -> {endInterface != null}");
|
||
}
|
||
|
||
// 根据连线类型重建
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重建圆柱体连线 - 使用保存的圆柱体数据
|
||
/// </summary>
|
||
private bool ReconstructCylinderWire(SerializableWireConnectionData wireData, GameObject startInterface, GameObject endInterface)
|
||
{
|
||
try
|
||
{
|
||
if (debugMode) Debug.Log($"重建圆柱体连线: {wireData.wireName}");
|
||
|
||
// 创建连线对象
|
||
GameObject wireObject = new GameObject(wireData.wireName);
|
||
|
||
// 添加 CylinderWireData 组件并设置数据
|
||
CylinderWireData cylinderData = wireObject.AddComponent<CylinderWireData>();
|
||
|
||
// 使用反射设置 CylinderWireData 的所有字段
|
||
SetCylinderWireDataFields(cylinderData, wireData, startInterface, endInterface);
|
||
|
||
// 创建圆柱体视觉表现 - 使用保存的圆柱体数据
|
||
CreateCylinderVisual(wireObject, wireData);
|
||
|
||
// 创建连接点
|
||
CreateConnectionPointsForWire(wireObject, wireData, startInterface, endInterface);
|
||
|
||
// 添加到连线系统
|
||
AddWireToSystem(wireObject, wireData, startInterface, endInterface);
|
||
|
||
if (debugMode)
|
||
{
|
||
Debug.Log($"WireDataPersistence: 成功重建圆柱体连线: {wireData.wireName}");
|
||
Debug.Log($"圆柱体缩放: {wireData.cylinderScale}, 位置: {wireData.cylinderPosition}");
|
||
}
|
||
return true;
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogError($"重建圆柱体连线失败: {e.Message}");
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 使用反射设置 CylinderWireData 的所有字段
|
||
/// </summary>
|
||
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":
|
||
field.SetValue(cylinderData, startInterface);
|
||
if (debugMode) Debug.Log($"设置 snapStartObject: {startInterface?.name ?? "null"}");
|
||
break;
|
||
case "snapEndObject":
|
||
field.SetValue(cylinderData, endInterface);
|
||
if (debugMode) Debug.Log($"设置 snapEndObject: {endInterface?.name ?? "null"}");
|
||
break;
|
||
case "creationTime":
|
||
field.SetValue(cylinderData, wireData.creationTime);
|
||
if (debugMode) Debug.Log($"设置 creationTime: {wireData.creationTime}");
|
||
break;
|
||
default:
|
||
// 尝试设置其他字段
|
||
if (debugMode) Debug.Log($"跳过字段: {field.Name} (类型: {field.FieldType})");
|
||
break;
|
||
}
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogWarning($"设置字段 {field.Name} 失败: {e.Message}");
|
||
}
|
||
}
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogError($"设置 CylinderWireData 字段失败: {e.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建圆柱体视觉表现 - 使用保存的圆柱体数据
|
||
/// </summary>
|
||
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}");
|
||
}
|
||
|
||
// 设置材质
|
||
if (cylinderWireMaterial != null)
|
||
{
|
||
Renderer renderer = cylinder.GetComponent<Renderer>();
|
||
if (renderer != null)
|
||
{
|
||
renderer.material = cylinderWireMaterial;
|
||
}
|
||
}
|
||
|
||
// 移除碰撞器
|
||
Collider collider = cylinder.GetComponent<Collider>();
|
||
if (collider != null)
|
||
{
|
||
DestroyImmediate(collider);
|
||
}
|
||
|
||
if (debugMode) Debug.Log($"圆柱体视觉创建完成: 位置={cylinder.transform.position}, 缩放={cylinder.transform.localScale}");
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogError($"创建圆柱体视觉失败: {e.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 为连线创建连接点
|
||
/// </summary>
|
||
private void CreateConnectionPointsForWire(GameObject wireObject, SerializableWireConnectionData wireData,
|
||
GameObject startInterface, GameObject endInterface)
|
||
{
|
||
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
|
||
);
|
||
|
||
if (startConnectionPoint != null)
|
||
{
|
||
startConnectionPoint.transform.SetParent(wireObject.transform);
|
||
}
|
||
}
|
||
|
||
// 创建终点连接点
|
||
if (wireData.endConnectionPointPosition != Vector3.zero)
|
||
{
|
||
GameObject endConnectionPoint = CreateConnectionPoint(
|
||
wireData.endConnectionPointPosition,
|
||
"ConnectionPoint_End_Restored",
|
||
connectionPointPrefab
|
||
);
|
||
|
||
if (endConnectionPoint != null)
|
||
{
|
||
endConnectionPoint.transform.SetParent(wireObject.transform);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Debug.LogWarning($"创建连接点失败: {e.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建连接点
|
||
/// </summary>
|
||
private GameObject CreateConnectionPoint(Vector3 position, string name, GameObject prefab)
|
||
{
|
||
if (prefab == null) return null;
|
||
|
||
GameObject connectionPoint = Instantiate(prefab);
|
||
connectionPoint.name = name;
|
||
connectionPoint.transform.position = position;
|
||
|
||
// 设置缩放
|
||
try
|
||
{
|
||
var connectionPointScaleField = typeof(WireDrawingSystem).GetField("connectionPointScale",
|
||
BindingFlags.Public | BindingFlags.Instance);
|
||
float connectionPointScale = connectionPointScaleField != null ?
|
||
(float)connectionPointScaleField.GetValue(wireSystem) : 0.1f;
|
||
connectionPoint.transform.localScale = Vector3.one * connectionPointScale;
|
||
}
|
||
catch
|
||
{
|
||
connectionPoint.transform.localScale = Vector3.one * 0.1f;
|
||
}
|
||
|
||
// 设置材质
|
||
try
|
||
{
|
||
var connectionPointMaterialField = typeof(WireDrawingSystem).GetField("connectionPointMaterial",
|
||
BindingFlags.Public | BindingFlags.Instance);
|
||
Material connectionPointMaterial = connectionPointMaterialField != null ?
|
||
(Material)connectionPointMaterialField.GetValue(wireSystem) : null;
|
||
|
||
if (connectionPointMaterial != null)
|
||
{
|
||
Renderer renderer = connectionPoint.GetComponent<Renderer>();
|
||
if (renderer != null)
|
||
{
|
||
renderer.material = connectionPointMaterial;
|
||
}
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
// 忽略材质设置错误
|
||
}
|
||
|
||
return connectionPoint;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将连线添加到连线系统
|
||
/// </summary>
|
||
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<GameObject> allWires = (List<GameObject>)allWiresField.GetValue(wireSystem);
|
||
if (allWires != null)
|
||
{
|
||
allWires.Add(wireObject);
|
||
}
|
||
}
|
||
|
||
// 添加连接点到列表
|
||
if (allConnectionPointsField != null)
|
||
{
|
||
List<GameObject> allConnectionPoints = (List<GameObject>)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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取连线的连接数据 - 关键修复方法,保存圆柱体数据
|
||
/// </summary>
|
||
private SerializableWireConnectionData GetWireConnectionData(GameObject wireObject)
|
||
{
|
||
try
|
||
{
|
||
if (wireObject == null)
|
||
{
|
||
if (debugMode) Debug.LogWarning("连线对象为 null");
|
||
return null;
|
||
}
|
||
|
||
// 方法1: 首先尝试从 CylinderWireData 组件获取
|
||
CylinderWireData cylinderData = wireObject.GetComponent<CylinderWireData>();
|
||
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 "snapStartObject":
|
||
GameObject startInterface = (GameObject)field.GetValue(cylinderData);
|
||
connectionData.startInterfaceName = startInterface ? startInterface.name : "";
|
||
connectionData.hasStartInterface = startInterface != null;
|
||
break;
|
||
case "snapEndObject":
|
||
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;
|
||
|
||
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;
|
||
}
|
||
else if (child.name.StartsWith("ConnectionPoint_End"))
|
||
{
|
||
connectionData.endConnectionPointPosition = child.position;
|
||
}
|
||
}
|
||
|
||
if (debugMode)
|
||
{
|
||
Debug.Log($"从 CylinderWireData 组件获取连线数据: {connectionData.wireName}");
|
||
Debug.Log($"起点: {connectionData.startPoint}, 终点: {connectionData.endPoint}");
|
||
}
|
||
return connectionData;
|
||
}
|
||
|
||
// 方法2: 尝试从 WireData 组件获取(兼容旧版本)
|
||
WireData wireDataComponent = wireObject.GetComponent<WireData>();
|
||
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;
|
||
}
|
||
else if (child.name.StartsWith("ConnectionPoint_End"))
|
||
{
|
||
connectionData.endConnectionPointPosition = child.position;
|
||
}
|
||
}
|
||
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据名称查找接口物体
|
||
/// </summary>
|
||
private GameObject FindInterfaceByName(string interfaceName)
|
||
{
|
||
if (string.IsNullOrEmpty(interfaceName))
|
||
return null;
|
||
|
||
// 在场景中查找物体
|
||
GameObject obj = GameObject.Find(interfaceName);
|
||
if (obj == null && debugMode)
|
||
{
|
||
Debug.LogWarning($"WireDataPersistence: 找不到接口物体: {interfaceName}");
|
||
}
|
||
|
||
return obj;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 手动保存
|
||
/// </summary>
|
||
public void ManualSave()
|
||
{
|
||
SaveWireData();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 手动加载
|
||
/// </summary>
|
||
public void ManualLoad()
|
||
{
|
||
LoadWireData();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除所有保存的数据
|
||
/// </summary>
|
||
public void ClearSavedData()
|
||
{
|
||
if (File.Exists(saveFilePath))
|
||
{
|
||
File.Delete(saveFilePath);
|
||
if (debugMode) Debug.Log("WireDataPersistence: 已清除保存的数据文件");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取保存信息
|
||
/// </summary>
|
||
public string GetSaveInfo()
|
||
{
|
||
if (File.Exists(saveFilePath))
|
||
{
|
||
FileInfo fileInfo = new FileInfo(saveFilePath);
|
||
try
|
||
{
|
||
string jsonData = File.ReadAllText(saveFilePath);
|
||
SerializableWireData data = JsonUtility.FromJson<SerializableWireData>(jsonData);
|
||
return $"WireDataPersistence: 已保存 {data.wires.Count} 条连线, 文件大小: {fileInfo.Length} 字节, 路径: {saveFilePath}";
|
||
}
|
||
catch
|
||
{
|
||
return $"WireDataPersistence: 文件存在但读取失败, 大小: {fileInfo.Length} 字节";
|
||
}
|
||
}
|
||
else
|
||
{
|
||
return "WireDataPersistence: 暂无保存数据";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否有保存的数据
|
||
/// </summary>
|
||
public bool HasSavedData()
|
||
{
|
||
return File.Exists(saveFilePath);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取保存文件路径
|
||
/// </summary>
|
||
public string GetSaveFilePath()
|
||
{
|
||
return saveFilePath;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前连线的统计信息
|
||
/// </summary>
|
||
public string GetWireStats()
|
||
{
|
||
if (!isInitialized || wireSystem == null) return "系统未初始化";
|
||
|
||
try
|
||
{
|
||
var allWiresField = typeof(WireDrawingSystem).GetField("allWires",
|
||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||
|
||
if (allWiresField == null) return "无法访问连线数据";
|
||
|
||
List<GameObject> allWires = (List<GameObject>)allWiresField.GetValue(wireSystem);
|
||
|
||
// 统计连线类型
|
||
int cylinderCount = 0;
|
||
int lineRendererCount = 0;
|
||
int unknownCount = 0;
|
||
|
||
if (allWires != null)
|
||
{
|
||
foreach (var wire in allWires)
|
||
{
|
||
if (wire != null)
|
||
{
|
||
if (wire.GetComponent<CylinderWireData>() != null) cylinderCount++;
|
||
else if (wire.GetComponent<LineRenderer>() != null) lineRendererCount++;
|
||
else unknownCount++;
|
||
}
|
||
}
|
||
}
|
||
|
||
return $"当前场景中有 {allWires?.Count ?? 0} 条连线 (圆柱体: {cylinderCount}, LineRenderer: {lineRendererCount}, 未知: {unknownCount})";
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
return $"获取统计信息失败: {e.Message}";
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 强制立即保存
|
||
/// </summary>
|
||
public void ForceSave()
|
||
{
|
||
SaveWireData();
|
||
}
|
||
|
||
//void OnApplicationQuit()
|
||
//{
|
||
// // 程序退出时自动保存
|
||
// if (enableAutoSave && isInitialized)
|
||
// {
|
||
// if (debugMode) Debug.Log("WireDataPersistence: 程序退出,保存数据");
|
||
// //SaveWireData();
|
||
// }
|
||
//}
|
||
|
||
//void OnDestroy()
|
||
//{
|
||
// // 组件销毁时自动保存
|
||
// if (enableAutoSave && isInitialized)
|
||
// {
|
||
// if (debugMode) Debug.Log("WireDataPersistence: 组件销毁,保存数据");
|
||
// //SaveWireData();
|
||
// }
|
||
//}
|
||
|
||
//void OnApplicationPause(bool pauseStatus)
|
||
//{
|
||
// // 应用暂停时保存(移动设备)
|
||
// if (pauseStatus && enableAutoSave && isInitialized)
|
||
// {
|
||
// if (debugMode) Debug.Log("WireDataPersistence: 应用暂停,保存数据");
|
||
// // SaveWireData();
|
||
// }
|
||
//}
|
||
} |