2050 lines
61 KiB
C#
2050 lines
61 KiB
C#
using UnityEngine;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
// 连线连接数据结构
|
||
[System.Serializable]
|
||
public class WireConnectionData
|
||
{
|
||
public GameObject startInterface;
|
||
public GameObject endInterface;
|
||
public GameObject startConnectionPoint;
|
||
public GameObject endConnectionPoint;
|
||
}
|
||
|
||
public class WireDrawingSystem : MonoBehaviour
|
||
{
|
||
public enum DrawingState
|
||
{
|
||
Idle, // 空闲状态
|
||
SelectingStart, // 选择起点
|
||
SelectingEnd // 选择终点
|
||
}
|
||
|
||
[Header("连线设置")]
|
||
public Material wireMaterial;
|
||
public Color wireColor = Color.red;
|
||
public float wireWidth = 0.02f;
|
||
|
||
[Header("吸附设置")]
|
||
public bool enableSnapping = true; // 启用吸附功能
|
||
public float snapDistance = 1.0f; // 吸附距离
|
||
public LayerMask snapLayers = -1; // 可吸附的层
|
||
public bool snapToColliderCenter = true; // 吸附到碰撞体中心
|
||
public bool snapToTransformCenter = false; // 吸附到变换组件中心
|
||
public Color snapHighlightColor = Color.cyan; // 吸附高亮颜色
|
||
|
||
[Header("高亮设置")]
|
||
public bool enableHighlight = true; // 启用点击物体高亮效果
|
||
public Color clickHighlightColor = Color.green; // 点击高亮颜色
|
||
public float highlightDuration = 1.0f; // 高亮持续时间
|
||
|
||
[Header("碰撞设置")]
|
||
public bool requireColliderForConnection = true; // 要求物体必须有碰撞体才能连线
|
||
public bool addColliderToWires = false; // 是否为连线添加碰撞器
|
||
|
||
[Header("状态显示")]
|
||
public DrawingState currentState = DrawingState.Idle;
|
||
|
||
// 连线数据
|
||
private Vector3 startPoint;
|
||
private Vector3 endPoint;
|
||
private LineRenderer currentWire;
|
||
private GameObject currentWireObject;
|
||
|
||
// 吸附相关
|
||
private GameObject snapTarget; // 当前吸附目标
|
||
private Renderer snapTargetRenderer; // 吸附目标的渲染器
|
||
public Color snapTargetOriginalColor = Color.blue; // 吸附目标原始颜色
|
||
private bool isSnapTargetHighlighted = false; // 新增:标记是否正在高亮
|
||
|
||
// 修复问题:记录鼠标点击的实际位置
|
||
private Vector3 actualMousePosition;
|
||
|
||
/// <summary>
|
||
/// 接线头样式
|
||
/// </summary>
|
||
[Header("接线头样式")]
|
||
public GameObject LineModel;
|
||
|
||
[Header("连接点模型设置")]
|
||
public GameObject connectionPointPrefab; // 连接点模型预制体
|
||
public float connectionPointScale = 0.1f; // 连接点模型缩放
|
||
public Material connectionPointMaterial; // 连接点材质
|
||
|
||
[Header("吸附点预览")]
|
||
public GameObject snapPreviewPrefab; // 吸附点预览预制体
|
||
private GameObject currentSnapPreview; // 当前吸附点预览
|
||
|
||
private List<GameObject> connectionPoints = new List<GameObject>(); // 存储所有连接点
|
||
|
||
[Header("删除设置")]
|
||
public KeyCode deleteKey = KeyCode.Mouse1; // 默认为鼠标右键
|
||
public float deleteDetectionRadius = 0.5f; // 删除检测半径
|
||
|
||
// 存储所有已创建的连线和连接点
|
||
private List<GameObject> allWires = new List<GameObject>();
|
||
private List<GameObject> allConnectionPoints = new List<GameObject>();
|
||
|
||
[Header("模型堆叠设置")]
|
||
public float verticalOffset = 0.2f; // 模型垂直偏移量
|
||
public bool enableStacking = true; // 启用模型堆叠
|
||
public int maxStackCount = 5; // 最大堆叠数量 (0表示无限制)
|
||
public Color maxStackWarningColor = Color.yellow; // 达到最大堆叠数量时的警告颜色
|
||
public Color selfConnectionWarningColor = Color.magenta; // 自连接警告颜色
|
||
|
||
// 存储每个接口上的模型堆叠信息
|
||
private Dictionary<GameObject, List<GameObject>> interfaceStacks = new Dictionary<GameObject, List<GameObject>>();
|
||
|
||
// 用于临时存储当前操作的目标接口
|
||
private GameObject currentStartInterface;
|
||
private GameObject currentEndInterface;
|
||
|
||
// 防止自连接
|
||
private GameObject startInterfaceObject;
|
||
private GameObject endInterfaceObject;
|
||
|
||
private bool isSnapTargetHighlighteds = false; // 新增:标记是否正在高亮
|
||
|
||
// 存储所有被高亮的接口,确保都能恢复颜色
|
||
private Dictionary<GameObject, Color> highlightedInterfaces = new Dictionary<GameObject, Color>();
|
||
// 连线数据存储
|
||
private Dictionary<GameObject, WireConnectionData> wireConnectionData = new Dictionary<GameObject, WireConnectionData>();
|
||
//存储接口的原始材质,防止材质实例化问题
|
||
private Dictionary<GameObject, Material> originalMaterials = new Dictionary<GameObject, Material>();
|
||
//存储当前高亮的接口,确保不会重复高亮
|
||
private GameObject currentlyHighlightedInterface = null;
|
||
|
||
// 高亮相关
|
||
private Coroutine currentHighlightCoroutine; // 当前高亮协程
|
||
private GameObject lastClickedObject; // 最后点击的物体
|
||
|
||
[Header("圆柱体连线设置")]
|
||
public bool useCylinderWire = true; // 启用圆柱体连线
|
||
public Material cylinderWireMaterial;
|
||
public float cylinderWireDiameter = 0.02f;
|
||
public int cylinderSegments = 8; // 圆柱体面数,影响性能
|
||
|
||
// 移除原来的LineRenderer相关设置,或者保留作为备选
|
||
[Header("传统连线设置(备选)")]
|
||
public bool useLineRenderer = false;
|
||
void Update()
|
||
{
|
||
HandleInput();
|
||
|
||
if (useCylinderWire)
|
||
{
|
||
UpdateCylinderWirePreview();
|
||
}
|
||
else
|
||
{
|
||
UpdateWirePreview(); // 原有的LineRenderer更新
|
||
}
|
||
|
||
// 在选择终点状态时检查吸附
|
||
if (currentState == DrawingState.SelectingEnd && enableSnapping)
|
||
{
|
||
CheckForSnapTargets();
|
||
UpdateSnapPreview();
|
||
}
|
||
else
|
||
{
|
||
ClearSnapPreview();
|
||
if (currentState != DrawingState.SelectingEnd)
|
||
{
|
||
ClearAllHighlights();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理点击物体高亮效果
|
||
/// </summary>
|
||
void HandleClickHighlight(GameObject clickedObject)
|
||
{
|
||
if (!enableHighlight || clickedObject == null) return;
|
||
|
||
// 停止之前的高亮协程
|
||
if (currentHighlightCoroutine != null)
|
||
{
|
||
StopCoroutine(currentHighlightCoroutine);
|
||
}
|
||
|
||
// 开始新的高亮协程
|
||
currentHighlightCoroutine = StartCoroutine(HighlightObject(clickedObject));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 高亮物体协程
|
||
/// </summary>
|
||
IEnumerator HighlightObject(GameObject targetObject)
|
||
{
|
||
if (targetObject == null) yield break;
|
||
|
||
Renderer renderer = targetObject.GetComponent<Renderer>();
|
||
if (renderer == null) yield break;
|
||
|
||
// 确保使用材质实例
|
||
EnsureMaterialInstance(targetObject);
|
||
|
||
// 记录原始颜色
|
||
Color originalColor = renderer.material.color;
|
||
if (!highlightedInterfaces.ContainsKey(targetObject))
|
||
{
|
||
highlightedInterfaces[targetObject] = originalColor;
|
||
}
|
||
|
||
// 设置高亮颜色
|
||
renderer.material.color = clickHighlightColor;
|
||
|
||
// 等待指定时间
|
||
yield return new WaitForSeconds(highlightDuration);
|
||
|
||
// 恢复原始颜色
|
||
if (renderer != null && targetObject != null)
|
||
{
|
||
if (highlightedInterfaces.ContainsKey(targetObject))
|
||
{
|
||
renderer.material.color = highlightedInterfaces[targetObject];
|
||
highlightedInterfaces.Remove(targetObject);
|
||
}
|
||
else
|
||
{
|
||
renderer.material.color = originalColor;
|
||
}
|
||
}
|
||
|
||
currentHighlightCoroutine = null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在指定位置创建连接点模型,支持在已有模型上方堆叠
|
||
/// </summary>
|
||
/// <param name="position">基础位置</param>
|
||
/// <param name="isStartPoint">是否为起点</param>
|
||
/// <param name="targetInterface">目标接口物体</param>
|
||
bool CreateConnectionPoint(Vector3 position, bool isStartPoint, GameObject targetInterface = null)
|
||
{
|
||
if (connectionPointPrefab == null)
|
||
{
|
||
Debug.LogWarning("连接点预制体未设置,无法创建连接点模型");
|
||
return false;
|
||
}
|
||
|
||
// 检查堆叠数量限制
|
||
if (targetInterface != null && enableStacking && IsStackLimitReached(targetInterface))
|
||
{
|
||
Debug.LogWarning($"接口 {targetInterface.name} 已达到最大堆叠数量限制 ({maxStackCount}),无法创建更多连接点");
|
||
ShowStackLimitWarning(targetInterface);
|
||
return false;
|
||
}
|
||
|
||
// 计算最终位置
|
||
Vector3 finalPosition = CalculateStackedPosition(position, targetInterface);
|
||
|
||
GameObject connectionPoint = Instantiate(connectionPointPrefab);
|
||
connectionPoint.name = $"ConnectionPoint_{(isStartPoint ? "Start" : "End")}_{System.DateTime.Now:HHmmss}";
|
||
connectionPoint.transform.position = finalPosition;
|
||
connectionPoint.transform.localScale = Vector3.one * connectionPointScale;
|
||
|
||
// 设置材质
|
||
if (connectionPointMaterial != null)
|
||
{
|
||
Renderer renderer = connectionPoint.GetComponent<Renderer>();
|
||
if (renderer != null)
|
||
{
|
||
renderer.material = connectionPointMaterial;
|
||
}
|
||
}
|
||
|
||
// 记录堆叠信息
|
||
if (targetInterface != null && enableStacking)
|
||
{
|
||
RegisterConnectionPointWithInterface(connectionPoint, targetInterface);
|
||
}
|
||
|
||
// 添加到连接点列表
|
||
allConnectionPoints.Add(connectionPoint);
|
||
|
||
Debug.Log($"创建连接点: {finalPosition}, 类型: {(isStartPoint ? "起点" : "终点")}, 目标接口: {targetInterface?.name ?? "无"}, 堆叠高度: {GetStackCountForInterface(targetInterface)}");
|
||
return true;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 检查接口是否达到堆叠数量限制
|
||
/// </summary>
|
||
bool IsStackLimitReached(GameObject targetInterface)
|
||
{
|
||
if (targetInterface == null || maxStackCount <= 0)
|
||
return false;
|
||
|
||
int currentCount = GetStackCountForInterface(targetInterface);
|
||
return currentCount >= maxStackCount;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否尝试自连接
|
||
/// </summary>
|
||
bool IsSelfConnection(GameObject targetInterface)
|
||
{
|
||
if (targetInterface == null || startInterfaceObject == null)
|
||
return false;
|
||
|
||
return targetInterface == startInterfaceObject;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示堆叠数量限制警告
|
||
/// </summary>
|
||
void ShowStackLimitWarning(GameObject targetInterface)
|
||
{
|
||
// 临时高亮显示达到限制的接口
|
||
Renderer renderer = targetInterface.GetComponent<Renderer>();
|
||
if (renderer != null)
|
||
{
|
||
// 确保使用材质实例
|
||
EnsureMaterialInstance(targetInterface);
|
||
|
||
// 记录原始颜色
|
||
if (!highlightedInterfaces.ContainsKey(targetInterface))
|
||
{
|
||
highlightedInterfaces[targetInterface] = renderer.material.color;
|
||
Debug.Log($"记录接口 {targetInterface.name} 的原始颜色(堆叠警告): {renderer.material.color}");
|
||
}
|
||
|
||
// StartCoroutine(FlashWarningColor(renderer, maxStackWarningColor, targetInterface));
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 显示自连接警告
|
||
/// </summary>
|
||
void ShowSelfConnectionWarning(GameObject targetInterface)
|
||
{
|
||
// 临时高亮显示自连接警告
|
||
Renderer renderer = targetInterface.GetComponent<Renderer>();
|
||
if (renderer != null)
|
||
{
|
||
// 确保使用材质实例
|
||
EnsureMaterialInstance(targetInterface);
|
||
|
||
// 记录原始颜色
|
||
if (!highlightedInterfaces.ContainsKey(targetInterface))
|
||
{
|
||
highlightedInterfaces[targetInterface] = renderer.material.color;
|
||
Debug.Log($"记录接口 {targetInterface.name} 的原始颜色(自连接警告): {renderer.material.color}");
|
||
}
|
||
|
||
//StartCoroutine(FlashWarningColor(renderer, selfConnectionWarningColor, targetInterface));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 闪烁警告颜色
|
||
/// </summary>
|
||
IEnumerator FlashWarningColor(Renderer targetRenderer, Color warningColor, GameObject targetInterface = null)
|
||
{
|
||
if (targetRenderer == null) yield break;
|
||
|
||
// 确保使用材质实例
|
||
if (targetInterface != null)
|
||
{
|
||
EnsureMaterialInstance(targetInterface);
|
||
}
|
||
|
||
// 保存当前颜色
|
||
Color currentColor = targetRenderer.material.color;
|
||
|
||
// 设置警告颜色
|
||
targetRenderer.material.color = warningColor;
|
||
Debug.Log($"设置接口 {targetInterface?.name} 为闪烁警告颜色: {warningColor}");
|
||
|
||
yield return new WaitForSeconds(0.5f);
|
||
|
||
if (targetRenderer != null && targetInterface != null)
|
||
{
|
||
// 恢复原始颜色
|
||
if (highlightedInterfaces.ContainsKey(targetInterface))
|
||
{
|
||
targetRenderer.material.color = highlightedInterfaces[targetInterface];
|
||
Debug.Log($"恢复接口 {targetInterface.name} 的原始颜色: {highlightedInterfaces[targetInterface]}");
|
||
}
|
||
else
|
||
{
|
||
targetRenderer.material.color = currentColor;
|
||
Debug.Log($"恢复接口 {targetInterface.name} 的当前颜色: {currentColor}");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 注册连接点到接口堆叠系统
|
||
/// </summary>
|
||
void RegisterConnectionPointWithInterface(GameObject connectionPoint, GameObject targetInterface)
|
||
{
|
||
if (targetInterface == null) return;
|
||
|
||
if (!interfaceStacks.ContainsKey(targetInterface))
|
||
{
|
||
interfaceStacks[targetInterface] = new List<GameObject>();
|
||
Debug.Log($"为接口 {targetInterface.name} 创建新堆叠列表");
|
||
}
|
||
|
||
interfaceStacks[targetInterface].Add(connectionPoint);
|
||
Debug.Log($"连接点 {connectionPoint.name} 已注册到接口 {targetInterface.name},当前总数: {interfaceStacks[targetInterface].Count}");
|
||
|
||
// 添加接口引用组件
|
||
ConnectionPointInterfaceReference refComponent = connectionPoint.GetComponent<ConnectionPointInterfaceReference>();
|
||
if (refComponent == null)
|
||
{
|
||
refComponent = connectionPoint.AddComponent<ConnectionPointInterfaceReference>();
|
||
}
|
||
refComponent.targetInterface = targetInterface;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从接口堆叠系统中移除连接点
|
||
/// </summary>
|
||
void UnregisterConnectionPointFromInterface(GameObject connectionPoint)
|
||
{
|
||
ConnectionPointInterfaceReference refComponent = connectionPoint.GetComponent<ConnectionPointInterfaceReference>();
|
||
if (refComponent != null && refComponent.targetInterface != null)
|
||
{
|
||
GameObject targetInterface = refComponent.targetInterface;
|
||
if (interfaceStacks.ContainsKey(targetInterface))
|
||
{
|
||
interfaceStacks[targetInterface].Remove(connectionPoint);
|
||
|
||
// 如果接口没有更多连接点,移除接口条目
|
||
if (interfaceStacks[targetInterface].Count == 0)
|
||
{
|
||
interfaceStacks.Remove(targetInterface);
|
||
}
|
||
|
||
// Debug.Log($"连接点 {connectionPoint.name} 已从接口 {targetInterface.name} 移除,剩余数量: {interfaceStacks.ContainsKey(targetInterface) ? interfaceStacks[targetInterface].Count : 0}");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算堆叠位置
|
||
/// </summary>
|
||
Vector3 CalculateStackedPosition(Vector3 basePosition, GameObject targetInterface)
|
||
{
|
||
if (targetInterface == null || !enableStacking)
|
||
{
|
||
Debug.Log("没有目标接口或堆叠功能已禁用,使用基础位置");
|
||
return basePosition;
|
||
}
|
||
|
||
int stackCount = GetStackCountForInterface(targetInterface);
|
||
Vector3 offset = Vector3.forward * (stackCount * verticalOffset);
|
||
Vector3 finalPosition = GetObjectCenter(targetInterface) + offset;
|
||
|
||
Debug.Log($"接口: {targetInterface.name}, 堆叠数量: {stackCount}, 基础位置: {basePosition}, 最终位置: {finalPosition}");
|
||
|
||
return finalPosition;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取接口上的模型堆叠数量
|
||
/// </summary>
|
||
int GetStackCountForInterface(GameObject targetInterface)
|
||
{
|
||
if (targetInterface == null || !interfaceStacks.ContainsKey(targetInterface))
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
// 清理已销毁的模型引用
|
||
interfaceStacks[targetInterface].RemoveAll(item => item == null);
|
||
return interfaceStacks[targetInterface].Count;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除未完成的连接点(用于取消操作时)
|
||
/// </summary>
|
||
void RemoveUnfinishedConnectionPoints()
|
||
{
|
||
// 删除最近创建但未完成的连接点
|
||
if (allConnectionPoints.Count > 0)
|
||
{
|
||
// 查找未附加到连线的连接点
|
||
List<GameObject> toRemove = new List<GameObject>();
|
||
foreach (GameObject point in allConnectionPoints)
|
||
{
|
||
if (point != null && point.transform.parent == null)
|
||
{
|
||
toRemove.Add(point);
|
||
}
|
||
}
|
||
|
||
// 删除这些连接点
|
||
foreach (GameObject point in toRemove)
|
||
{
|
||
// 从接口堆叠系统中移除
|
||
UnregisterConnectionPointFromInterface(point);
|
||
|
||
allConnectionPoints.Remove(point);
|
||
Destroy(point);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除所有连接点
|
||
/// </summary>
|
||
public void ClearAllConnectionPoints()
|
||
{
|
||
foreach (GameObject point in connectionPoints)
|
||
{
|
||
if (point != null)
|
||
Destroy(point);
|
||
}
|
||
connectionPoints.Clear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除所有连线和连接点
|
||
/// </summary>
|
||
public void ClearAll()
|
||
{
|
||
// 创建连线列表的副本,避免在遍历时修改集合
|
||
List<GameObject> wiresToDelete = new List<GameObject>(allWires);
|
||
foreach (GameObject wire in wiresToDelete)
|
||
{
|
||
if (wire != null)
|
||
DeleteWire(wire);
|
||
}
|
||
allWires.Clear();
|
||
|
||
// 创建连接点列表的副本
|
||
List<GameObject> pointsToDelete = new List<GameObject>(allConnectionPoints);
|
||
foreach (GameObject point in pointsToDelete)
|
||
{
|
||
if (point != null)
|
||
DeleteConnectionPoint(point);
|
||
}
|
||
allConnectionPoints.Clear();
|
||
|
||
// 清除堆叠信息
|
||
interfaceStacks.Clear();
|
||
|
||
// 清除连线数据
|
||
wireConnectionData.Clear();
|
||
|
||
// 清除吸附点预览
|
||
ClearSnapPreview();
|
||
|
||
// 清除所有高亮
|
||
ClearAllHighlights();
|
||
|
||
// 恢复所有接口的原始材质
|
||
List<GameObject> interfacesToRestore = new List<GameObject>(originalMaterials.Keys);
|
||
foreach (GameObject interfaceObj in interfacesToRestore)
|
||
{
|
||
if (interfaceObj != null)
|
||
{
|
||
RestoreOriginalMaterial(interfaceObj);
|
||
}
|
||
}
|
||
originalMaterials.Clear();
|
||
|
||
Debug.Log("已清除所有连线和连接点");
|
||
}
|
||
/// <summary>
|
||
/// 将连接点附加到连线对象上
|
||
/// </summary>
|
||
/// <param name="wireObject">连线对象</param>
|
||
void AttachConnectionPointsToWire(GameObject wireObject)
|
||
{
|
||
// 查找最近创建的两个未附加的连接点
|
||
List<GameObject> unattachedPoints = new List<GameObject>();
|
||
foreach (GameObject point in allConnectionPoints)
|
||
{
|
||
if (point != null && point.transform.parent == null)
|
||
{
|
||
unattachedPoints.Add(point);
|
||
}
|
||
}
|
||
|
||
// 将最近的两个连接点附加到连线
|
||
if (unattachedPoints.Count >= 2)
|
||
{
|
||
for (int i = unattachedPoints.Count - 1; i >= Mathf.Max(0, unattachedPoints.Count - 2); i--)
|
||
{
|
||
unattachedPoints[i].transform.SetParent(wireObject.transform);
|
||
}
|
||
}
|
||
}
|
||
|
||
void HandleInput()
|
||
{
|
||
if (Input.GetMouseButtonDown(0)) // 左键点击
|
||
{
|
||
HandleMouseClick();
|
||
}
|
||
|
||
if (Input.GetKeyDown(KeyCode.Escape))// 取消当前操作
|
||
{
|
||
CancelDrawing();
|
||
}
|
||
if (Input.GetMouseButtonDown(2))
|
||
{
|
||
HandleDelete();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理删除操作
|
||
/// </summary>
|
||
void HandleDelete()
|
||
{
|
||
// 首先清除所有高亮,确保颜色恢复
|
||
ClearAllHighlights();
|
||
|
||
// 如果正在绘制连线,先取消绘制
|
||
if (currentState != DrawingState.Idle)
|
||
{
|
||
CancelDrawing();
|
||
return;
|
||
}
|
||
|
||
// 清除吸附点预览
|
||
ClearSnapPreview();
|
||
|
||
// 查找鼠标位置附近的连线和连接点
|
||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||
RaycastHit hit;
|
||
|
||
bool foundObjectToDelete = false;
|
||
|
||
if (Physics.Raycast(ray, out hit, Mathf.Infinity))
|
||
{
|
||
// 检查是否点击到了连线或连接点
|
||
GameObject hitObject = hit.collider.gameObject;
|
||
if (IsWireOrConnection(hitObject))
|
||
{
|
||
DeleteObjectIfWireOrConnection(hitObject);
|
||
foundObjectToDelete = true;
|
||
}
|
||
}
|
||
|
||
// 如果没有找到可删除的对象,尝试删除最后一个连线
|
||
if (!foundObjectToDelete)
|
||
{
|
||
DeleteLastWire();
|
||
}
|
||
|
||
// 删除后再次确保清除所有高亮
|
||
ClearAllHighlights();
|
||
}
|
||
/// <summary>
|
||
/// 检查对象是否是连线或连接点
|
||
/// </summary>
|
||
bool IsWireOrConnection(GameObject obj)
|
||
{
|
||
if (obj == null) return false;
|
||
|
||
// 检查是否是连线
|
||
if (obj.name.StartsWith("Wire_") || obj.GetComponent<LineRenderer>() != null)
|
||
{
|
||
return true;
|
||
}
|
||
|
||
// 检查是否是连接点
|
||
if (obj.name.StartsWith("ConnectionPoint_"))
|
||
{
|
||
return true;
|
||
}
|
||
|
||
// 检查是否是连线的一部分(子物体)
|
||
if (obj.transform.parent != null)
|
||
{
|
||
GameObject parent = obj.transform.parent.gameObject;
|
||
if (parent.name.StartsWith("Wire_") || parent.GetComponent<LineRenderer>() != null)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
|
||
return false;
|
||
}
|
||
/// <summary>
|
||
/// 清除所有高亮接口的颜色
|
||
/// </summary>
|
||
void ClearAllHighlights()
|
||
{
|
||
// 恢复所有被高亮接口的原始颜色
|
||
List<GameObject> interfacesToRestore = new List<GameObject>(highlightedInterfaces.Keys);
|
||
foreach (GameObject interfaceObj in interfacesToRestore)
|
||
{
|
||
if (interfaceObj != null)
|
||
{
|
||
RestoreInterfaceColor(interfaceObj);
|
||
}
|
||
}
|
||
highlightedInterfaces.Clear();
|
||
|
||
// 清除当前吸附目标的高亮
|
||
if (snapTargetRenderer != null && isSnapTargetHighlighted)
|
||
{
|
||
// 如果当前吸附目标不在字典中,使用保存的原始颜色
|
||
if (!highlightedInterfaces.ContainsKey(snapTarget))
|
||
{
|
||
// snapTargetRenderer.material.color = snapTargetOriginalColor;
|
||
Debug.Log($"恢复吸附目标 {snapTarget?.name} 的原始颜色: {snapTargetOriginalColor}");
|
||
}
|
||
snapTargetRenderer = null;
|
||
isSnapTargetHighlighted = false;
|
||
}
|
||
|
||
// 停止点击高亮协程
|
||
if (currentHighlightCoroutine != null)
|
||
{
|
||
StopCoroutine(currentHighlightCoroutine);
|
||
currentHighlightCoroutine = null;
|
||
}
|
||
|
||
// 重置当前高亮接口
|
||
currentlyHighlightedInterface = null;
|
||
snapTarget = null;
|
||
}
|
||
/// <summary>
|
||
/// 恢复单个接口的颜色
|
||
/// </summary>
|
||
void RestoreInterfaceColor(GameObject interfaceObject)
|
||
{
|
||
if (interfaceObject == null) return;
|
||
|
||
Renderer renderer = interfaceObject.GetComponent<Renderer>();
|
||
if (renderer != null)
|
||
{
|
||
// 如果这个接口在记录中,使用记录的颜色
|
||
if (highlightedInterfaces.ContainsKey(interfaceObject))
|
||
{
|
||
Color originalColor = highlightedInterfaces[interfaceObject];
|
||
renderer.material.color = originalColor;
|
||
Debug.Log($"恢复接口 {interfaceObject.name} 的原始颜色: {originalColor}");
|
||
|
||
// 从字典中移除,避免重复恢复
|
||
highlightedInterfaces.Remove(interfaceObject);
|
||
}
|
||
//else
|
||
//{
|
||
// // 如果不在字典中,尝试使用默认颜色
|
||
// renderer.material.color = new Color(0.85f, 0.71f, 0.4f);
|
||
// Debug.Log($"设置接口 {interfaceObject.name} 为默认白色");
|
||
//}
|
||
|
||
// 恢复原始材质
|
||
RestoreOriginalMaterial(interfaceObject);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除指定的连线或连接点
|
||
/// </summary>
|
||
void DeleteObjectIfWireOrConnection(GameObject obj)
|
||
{
|
||
if (obj == null) return;
|
||
|
||
// 检查是否是吸附预览
|
||
if (obj.name == "SnapPreview")
|
||
{
|
||
ClearSnapPreview();
|
||
return;
|
||
}
|
||
|
||
// 检查是否是连线
|
||
if (obj.name.StartsWith("Wire_") || obj.GetComponent<LineRenderer>() != null)
|
||
{
|
||
DeleteWire(obj);
|
||
return;
|
||
}
|
||
|
||
// 检查是否是连接点
|
||
if (obj.name.StartsWith("ConnectionPoint_"))
|
||
{
|
||
// 如果是连接点,找到其父连线并删除
|
||
if (obj.transform.parent != null)
|
||
{
|
||
GameObject parent = obj.transform.parent.gameObject;
|
||
if (parent.name.StartsWith("Wire_") || parent.GetComponent<LineRenderer>() != null)
|
||
{
|
||
DeleteWire(parent);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 如果没有父连线,单独删除连接点
|
||
DeleteConnectionPoint(obj);
|
||
return;
|
||
}
|
||
|
||
// 检查是否是连线的一部分(子物体)
|
||
if (obj.transform.parent != null)
|
||
{
|
||
GameObject parent = obj.transform.parent.gameObject;
|
||
if (parent.name.StartsWith("Wire_") || parent.GetComponent<LineRenderer>() != null)
|
||
{
|
||
DeleteWire(parent);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 如果没有匹配的类型,尝试删除最后一个连线
|
||
Debug.Log("未找到可删除的对象,尝试删除最后一个连线");
|
||
DeleteLastWire();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 删除指定的连线
|
||
/// </summary>
|
||
void DeleteWire(GameObject wireObject)
|
||
{
|
||
if (wireObject == null)
|
||
{
|
||
Debug.LogWarning("尝试删除空的连线对象");
|
||
return;
|
||
}
|
||
|
||
Debug.Log($"开始删除连线: {wireObject.name}");
|
||
|
||
// 获取连线数据
|
||
WireData wireData = wireObject.GetComponent<WireData>();
|
||
GameObject startInterface = null;
|
||
GameObject endInterface = null;
|
||
|
||
if (wireData != null)
|
||
{
|
||
startInterface = wireData.snapStartObject;
|
||
endInterface = wireData.snapEndObject;
|
||
}
|
||
else
|
||
{
|
||
// 尝试从存储的数据中获取
|
||
if (wireConnectionData.ContainsKey(wireObject))
|
||
{
|
||
startInterface = wireConnectionData[wireObject].startInterface;
|
||
endInterface = wireConnectionData[wireObject].endInterface;
|
||
}
|
||
}
|
||
|
||
// 删除连线的所有连接点(子物体)
|
||
foreach (Transform child in wireObject.transform)
|
||
{
|
||
if (child.name.StartsWith("ConnectionPoint_"))
|
||
{
|
||
Debug.Log($"删除连接点: {child.name}");
|
||
|
||
// 从接口堆叠系统中移除
|
||
UnregisterConnectionPointFromInterface(child.gameObject);
|
||
|
||
allConnectionPoints.Remove(child.gameObject);
|
||
Destroy(child.gameObject);
|
||
}
|
||
}
|
||
|
||
// 从列表中移除并销毁连线
|
||
bool removedFromList = allWires.Remove(wireObject);
|
||
if (removedFromList)
|
||
{
|
||
Debug.Log($"从连线列表中移除: {wireObject.name}");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"连线 {wireObject.name} 不在连线列表中");
|
||
}
|
||
|
||
// 从连线数据存储中移除
|
||
if (wireConnectionData.ContainsKey(wireObject))
|
||
{
|
||
wireConnectionData.Remove(wireObject);
|
||
}
|
||
|
||
Destroy(wireObject);
|
||
Debug.Log($"销毁连线对象: {wireObject.name}");
|
||
|
||
// 恢复连线两端接口的颜色和材质
|
||
if (startInterface != null)
|
||
{
|
||
RestoreInterfaceColor(startInterface);
|
||
RestoreOriginalMaterial(startInterface);
|
||
Debug.Log($"恢复起点接口颜色和材质: {startInterface.name}");
|
||
}
|
||
if (endInterface != null)
|
||
{
|
||
RestoreInterfaceColor(endInterface);
|
||
RestoreOriginalMaterial(endInterface);
|
||
Debug.Log($"恢复终点接口颜色和材质: {endInterface.name}");
|
||
}
|
||
|
||
// 清除吸附点预览和高亮
|
||
ClearSnapPreview();
|
||
ClearAllHighlights();
|
||
|
||
Debug.Log($"连线删除完成: {wireObject.name}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除指定的连接点
|
||
/// </summary>
|
||
void DeleteConnectionPoint(GameObject connectionPoint)
|
||
{
|
||
if (connectionPoint == null)
|
||
{
|
||
Debug.LogWarning("尝试删除空的连接点对象");
|
||
return;
|
||
}
|
||
|
||
Debug.Log($"开始删除连接点: {connectionPoint.name}");
|
||
|
||
// 获取连接点对应的接口
|
||
ConnectionPointInterfaceReference refComponent = connectionPoint.GetComponent<ConnectionPointInterfaceReference>();
|
||
GameObject targetInterface = refComponent?.targetInterface;
|
||
|
||
// 从接口堆叠系统中移除
|
||
UnregisterConnectionPointFromInterface(connectionPoint);
|
||
|
||
// 从列表中移除并销毁连接点
|
||
bool removedFromList = allConnectionPoints.Remove(connectionPoint);
|
||
if (removedFromList)
|
||
{
|
||
Debug.Log($"从连接点列表中移除: {connectionPoint.name}");
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"连接点 {connectionPoint.name} 不在连接点列表中");
|
||
}
|
||
|
||
Destroy(connectionPoint);
|
||
Debug.Log($"销毁连接点对象: {connectionPoint.name}");
|
||
|
||
// 恢复对应接口的颜色和材质
|
||
if (targetInterface != null)
|
||
{
|
||
RestoreInterfaceColor(targetInterface);
|
||
RestoreOriginalMaterial(targetInterface);
|
||
Debug.Log($"恢复接口颜色和材质: {targetInterface.name}");
|
||
}
|
||
|
||
// 清除吸附点预览和高亮
|
||
ClearSnapPreview();
|
||
ClearAllHighlights();
|
||
|
||
Debug.Log($"连接点删除完成: {connectionPoint.name}");
|
||
}
|
||
/// <summary>
|
||
/// 删除最后一个创建的连线
|
||
/// </summary>
|
||
void DeleteLastWire()
|
||
{
|
||
if (allWires.Count > 0)
|
||
{
|
||
GameObject lastWire = allWires[allWires.Count - 1];
|
||
Debug.Log($"删除最后一个连线: {lastWire.name}");
|
||
DeleteWire(lastWire);
|
||
}
|
||
else
|
||
{
|
||
Debug.Log("没有可删除的连线");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 删除最后一个连接点
|
||
/// </summary>
|
||
void DeleteLastConnectionPoint()
|
||
{
|
||
if (allConnectionPoints.Count > 0)
|
||
{
|
||
GameObject lastPoint = allConnectionPoints[allConnectionPoints.Count - 1];
|
||
DeleteConnectionPoint(lastPoint);
|
||
}
|
||
else
|
||
{
|
||
Debug.Log("没有可删除的连接点");
|
||
}
|
||
}
|
||
|
||
void HandleMouseClick()
|
||
{
|
||
// 首先清除所有可能的高亮状态
|
||
ClearAllHighlights();
|
||
|
||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||
RaycastHit hit;
|
||
|
||
// 获取鼠标的实际世界位置
|
||
actualMousePosition = GetMouseWorldPosition();
|
||
|
||
// 重置当前接口
|
||
currentStartInterface = null;
|
||
currentEndInterface = null;
|
||
|
||
// 首先检查是否有吸附目标
|
||
if (snapTarget != null)
|
||
{
|
||
// 检查吸附目标是否有碰撞体
|
||
if (requireColliderForConnection && !HasCollider(snapTarget))
|
||
{
|
||
Debug.LogWarning($"目标物体 {snapTarget.name} 没有碰撞体,无法连线");
|
||
return;
|
||
}
|
||
|
||
// 检查是否尝试自连接
|
||
if (currentState == DrawingState.SelectingEnd && IsSelfConnection(snapTarget))
|
||
{
|
||
Debug.LogWarning("不能连接到自身接口!");
|
||
ShowSelfConnectionWarning(snapTarget);
|
||
return;
|
||
}
|
||
|
||
// 应用点击高亮效果
|
||
HandleClickHighlight(snapTarget);
|
||
|
||
// 如果有吸附目标,使用吸附点的位置
|
||
Vector3 targetPoint = GetObjectCenter(snapTarget);
|
||
|
||
// 设置当前接口
|
||
if (currentState == DrawingState.Idle)
|
||
{
|
||
currentStartInterface = snapTarget;
|
||
startInterfaceObject = snapTarget; // 记录起点接口
|
||
}
|
||
else if (currentState == DrawingState.SelectingEnd)
|
||
{
|
||
currentEndInterface = snapTarget;
|
||
}
|
||
|
||
switch (currentState)
|
||
{
|
||
case DrawingState.Idle:
|
||
StartNewWire(targetPoint);
|
||
break;
|
||
|
||
case DrawingState.SelectingStart:
|
||
break;
|
||
|
||
case DrawingState.SelectingEnd:
|
||
CompleteWire(targetPoint);
|
||
break;
|
||
}
|
||
}
|
||
else if (Physics.Raycast(ray, out hit, Mathf.Infinity, snapLayers))
|
||
{
|
||
GameObject hitObject = hit.collider.gameObject;
|
||
|
||
// 检查击中的物体是否有碰撞体
|
||
if (requireColliderForConnection && !HasCollider(hitObject))
|
||
{
|
||
Debug.LogWarning($"目标物体 {hitObject.name} 没有碰撞体,无法连线");
|
||
return;
|
||
}
|
||
|
||
// 检查是否尝试自连接
|
||
if (currentState == DrawingState.SelectingEnd && IsSelfConnection(hitObject))
|
||
{
|
||
Debug.LogWarning("不能连接到自身接口!");
|
||
ShowSelfConnectionWarning(hitObject);
|
||
return;
|
||
}
|
||
|
||
// 应用点击高亮效果
|
||
HandleClickHighlight(hitObject);
|
||
|
||
// 如果有击中物体,使用击中点的位置
|
||
Vector3 targetPoint = GetSnapPoint(hit);
|
||
|
||
// 检查是否在吸附距离内,如果是则设置当前接口
|
||
Vector3 objectCenter = GetObjectCenter(hitObject);
|
||
float distance = Vector3.Distance(hit.point, objectCenter);
|
||
if (distance <= snapDistance)
|
||
{
|
||
if (currentState == DrawingState.Idle)
|
||
{
|
||
currentStartInterface = hitObject;
|
||
startInterfaceObject = hitObject; // 记录起点接口
|
||
}
|
||
else if (currentState == DrawingState.SelectingEnd)
|
||
{
|
||
currentEndInterface = hitObject;
|
||
}
|
||
}
|
||
|
||
switch (currentState)
|
||
{
|
||
case DrawingState.Idle:
|
||
StartNewWire(targetPoint);
|
||
break;
|
||
|
||
case DrawingState.SelectingStart:
|
||
break;
|
||
|
||
case DrawingState.SelectingEnd:
|
||
CompleteWire(targetPoint);
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 如果没有击中任何物体,且要求必须有碰撞体,则不允许连线
|
||
if (requireColliderForConnection)
|
||
{
|
||
Debug.LogWarning("没有找到带有碰撞体的物体,无法连线");
|
||
return;
|
||
}
|
||
|
||
// 如果没有击中任何物体,使用实际鼠标位置
|
||
switch (currentState)
|
||
{
|
||
case DrawingState.Idle:
|
||
StartNewWire(actualMousePosition);
|
||
break;
|
||
|
||
case DrawingState.SelectingStart:
|
||
break;
|
||
|
||
case DrawingState.SelectingEnd:
|
||
CompleteWire(actualMousePosition);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
// 检查物体是否有碰撞体
|
||
bool HasCollider(GameObject obj)
|
||
{
|
||
if (obj == null) return false;
|
||
|
||
// 检查所有类型的碰撞器
|
||
Collider collider3D = obj.GetComponent<Collider>();
|
||
Collider2D collider2D = obj.GetComponent<Collider2D>();
|
||
|
||
return (collider3D != null || collider2D != null);
|
||
}
|
||
|
||
// 修改 StartNewWire 方法,传递目标接口
|
||
void StartNewWire(Vector3 point)
|
||
{
|
||
startPoint = point;
|
||
currentState = DrawingState.SelectingEnd;
|
||
|
||
// 记录起点接口
|
||
startInterfaceObject = currentStartInterface;
|
||
|
||
// 创建起点连接点模型,传递当前接口
|
||
bool created = CreateConnectionPoint(point, true, startInterfaceObject);
|
||
if (!created)
|
||
{
|
||
// 如果创建失败,取消连线操作
|
||
currentState = DrawingState.Idle;
|
||
startInterfaceObject = null;
|
||
return;
|
||
}
|
||
|
||
CreateWirePreview();
|
||
Debug.Log($"选择起点: {point}, 接口: {startInterfaceObject?.name ?? "无"}");
|
||
}
|
||
|
||
// 修改 CompleteWire 方法,传递目标接口
|
||
void CompleteWire(Vector3 point)
|
||
{
|
||
// 记录终点接口
|
||
endInterfaceObject = currentEndInterface;
|
||
|
||
// 最终检查是否尝试自连接
|
||
if (endInterfaceObject != null && IsSelfConnection(endInterfaceObject))
|
||
{
|
||
Debug.LogWarning("不能连接到自身接口!");
|
||
ShowSelfConnectionWarning(endInterfaceObject);
|
||
CancelDrawing();
|
||
return;
|
||
}
|
||
|
||
// 检查终点堆叠限制
|
||
if (endInterfaceObject != null && enableStacking && IsStackLimitReached(endInterfaceObject))
|
||
{
|
||
Debug.LogWarning($"终点接口 {endInterfaceObject.name} 已达到堆叠限制,无法连接");
|
||
ShowStackLimitWarning(endInterfaceObject);
|
||
CancelDrawing();
|
||
return;
|
||
}
|
||
|
||
endPoint = point;
|
||
currentState = DrawingState.Idle;
|
||
|
||
// 创建终点连接点模型,传递当前接口
|
||
bool created = CreateConnectionPoint(point, false, endInterfaceObject);
|
||
if (!created)
|
||
{
|
||
// 如果创建失败,删除起点连接点并取消连线
|
||
RemoveUnfinishedConnectionPoints();
|
||
startInterfaceObject = null;
|
||
endInterfaceObject = null;
|
||
return;
|
||
}
|
||
|
||
FinalizeWire();
|
||
Debug.Log($"选择终点: {point}, 接口: {endInterfaceObject?.name ?? "无"}");
|
||
|
||
// 清除所有高亮,确保颜色恢复
|
||
ClearAllHighlights();
|
||
|
||
// 重置当前接口
|
||
currentStartInterface = null;
|
||
currentEndInterface = null;
|
||
startInterfaceObject = null;
|
||
endInterfaceObject = null;
|
||
}
|
||
|
||
void CreateWirePreview()
|
||
{
|
||
currentWireObject = new GameObject("WirePreview");
|
||
|
||
if (useCylinderWire)
|
||
{
|
||
CreateCylinderWirePreview();
|
||
}
|
||
else
|
||
{
|
||
// 原有的LineRenderer代码
|
||
currentWire = currentWireObject.AddComponent<LineRenderer>();
|
||
ConfigureLineRenderer(currentWire);
|
||
currentWire.positionCount = 2;
|
||
currentWire.SetPosition(0, startPoint);
|
||
currentWire.SetPosition(1, startPoint);
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 创建圆柱体连线预览
|
||
/// </summary>
|
||
void CreateCylinderWirePreview()
|
||
{
|
||
// 创建初始圆柱体(长度很短)
|
||
GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
|
||
cylinder.name = "WireCylinder";
|
||
cylinder.transform.SetParent(currentWireObject.transform);
|
||
|
||
// 设置材质
|
||
if (cylinderWireMaterial != null)
|
||
{
|
||
Renderer renderer = cylinder.GetComponent<Renderer>();
|
||
renderer.material = cylinderWireMaterial;
|
||
}
|
||
|
||
// 初始位置和缩放
|
||
cylinder.transform.position = startPoint;
|
||
cylinder.transform.localScale = new Vector3(
|
||
cylinderWireDiameter,
|
||
0.001f, // 初始高度很小
|
||
cylinderWireDiameter
|
||
);
|
||
|
||
// 移除碰撞器,避免干扰
|
||
Destroy(cylinder.GetComponent<Collider>());
|
||
}
|
||
/// <summary>
|
||
/// 更新圆柱体连线预览
|
||
/// </summary>
|
||
void UpdateCylinderWirePreview()
|
||
{
|
||
if (currentState == DrawingState.SelectingEnd && currentWireObject != null)
|
||
{
|
||
Vector3 targetPoint;
|
||
|
||
if (snapTarget != null)
|
||
{
|
||
targetPoint = GetObjectCenter(snapTarget);
|
||
}
|
||
else
|
||
{
|
||
targetPoint = GetMouseWorldPosition();
|
||
}
|
||
|
||
if (useCylinderWire)
|
||
{
|
||
UpdateCylinderWire(startPoint, targetPoint);
|
||
}
|
||
else
|
||
{
|
||
// 原有的LineRenderer更新代码
|
||
if (currentWire != null)
|
||
{
|
||
currentWire.SetPosition(1, targetPoint);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 更新圆柱体连线的位置和形状
|
||
/// </summary>
|
||
void UpdateCylinderWire(Vector3 start, Vector3 end)
|
||
{
|
||
Transform cylinderTransform = currentWireObject.transform.Find("WireCylinder");
|
||
if (cylinderTransform == null) return;
|
||
|
||
GameObject cylinder = cylinderTransform.gameObject;
|
||
|
||
// 计算连线的方向、长度和中点
|
||
Vector3 direction = end - start;
|
||
float distance = direction.magnitude;
|
||
|
||
if (distance < 0.001f)
|
||
{
|
||
// 距离太短,隐藏圆柱体
|
||
cylinder.transform.localScale = new Vector3(cylinderWireDiameter, 0.001f, cylinderWireDiameter);
|
||
return;
|
||
}
|
||
|
||
Vector3 midPoint = (start + end) / 2f;
|
||
|
||
// 设置圆柱体的位置和旋转
|
||
cylinder.transform.position = midPoint;
|
||
cylinder.transform.up = direction.normalized; // 圆柱体默认朝向Y轴
|
||
|
||
// 设置圆柱体的缩放
|
||
// 圆柱体原始高度为2,所以实际高度 = scaleY * 2
|
||
cylinder.transform.localScale = new Vector3(
|
||
cylinderWireDiameter,
|
||
distance / 2f, // 因为原始高度为2,所以要除以2
|
||
cylinderWireDiameter
|
||
);
|
||
}
|
||
/// <summary>
|
||
/// 最终确定圆柱体连线
|
||
/// </summary>
|
||
void FinalizeCylinderWire()
|
||
{
|
||
if (currentWireObject == null) return;
|
||
|
||
Transform cylinderTransform = currentWireObject.transform.Find("WireCylinder");
|
||
if (cylinderTransform == null) return;
|
||
|
||
GameObject cylinder = cylinderTransform.gameObject;
|
||
|
||
// 更新最终位置
|
||
UpdateCylinderWire(startPoint, endPoint);
|
||
|
||
// 添加圆柱体连线数据
|
||
CylinderWireData wireData = currentWireObject.AddComponent<CylinderWireData>();
|
||
wireData.startPoint = GetConnectionPointObject(true);
|
||
wireData.endPoint = GetConnectionPointObject(false);
|
||
wireData.startInterface = startInterfaceObject;
|
||
wireData.endInterface = endInterfaceObject;
|
||
wireData.wireDiameter = cylinderWireDiameter;
|
||
|
||
// 可选:添加碰撞器
|
||
if (addColliderToWires)
|
||
{
|
||
AddCylinderWireCollider(cylinder);
|
||
}
|
||
|
||
// 添加到连线列表
|
||
allWires.Add(currentWireObject);
|
||
|
||
Debug.Log($"圆柱体连线完成: {currentWireObject.name}");
|
||
}
|
||
/// <summary>
|
||
/// 获取连接点对象(用于连线数据)
|
||
/// </summary>
|
||
GameObject GetConnectionPointObject(bool isStartPoint)
|
||
{
|
||
// 查找最近创建的连接点
|
||
for (int i = allConnectionPoints.Count - 1; i >= 0; i--)
|
||
{
|
||
GameObject point = allConnectionPoints[i];
|
||
if (point != null && point.transform.parent == null)
|
||
{
|
||
if (isStartPoint && point.name.Contains("Start"))
|
||
return point;
|
||
else if (!isStartPoint && point.name.Contains("End"))
|
||
return point;
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
/// <summary>
|
||
/// 为圆柱体连线添加碰撞器
|
||
/// </summary>
|
||
void AddCylinderWireCollider(GameObject cylinder)
|
||
{
|
||
CapsuleCollider collider = cylinder.AddComponent<CapsuleCollider>();
|
||
collider.isTrigger = true;
|
||
|
||
// 胶囊碰撞器会自动匹配圆柱体的形状
|
||
// 方向设置为Y轴(圆柱体的默认方向)
|
||
collider.direction = 1; // 1 = Y轴
|
||
}
|
||
void UpdateWirePreview()
|
||
{
|
||
if (currentState == DrawingState.SelectingEnd && currentWire != null)
|
||
{
|
||
Vector3 targetPoint;
|
||
|
||
// 如果有吸附目标,使用吸附点
|
||
if (snapTarget != null)
|
||
{
|
||
targetPoint = GetObjectCenter(snapTarget);
|
||
}
|
||
else
|
||
{
|
||
// 否则使用实际鼠标位置
|
||
targetPoint = GetMouseWorldPosition();
|
||
}
|
||
|
||
currentWire.SetPosition(1, targetPoint);
|
||
}
|
||
}
|
||
|
||
void CheckForSnapTargets()
|
||
{
|
||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||
RaycastHit hit;
|
||
|
||
// 清除之前的吸附高亮
|
||
ClearSnapHighlight();
|
||
|
||
// 检查鼠标位置附近是否有可吸附的物体
|
||
if (Physics.Raycast(ray, out hit, Mathf.Infinity, snapLayers))
|
||
{
|
||
GameObject hitObject = hit.collider.gameObject;
|
||
|
||
// 如果要求碰撞体但物体没有碰撞体,跳过
|
||
if (requireColliderForConnection && !HasCollider(hitObject))
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 检查是否尝试自连接
|
||
if (currentState == DrawingState.SelectingEnd && IsSelfConnection(hitObject))
|
||
{
|
||
// 自连接目标仍然可以吸附,但会显示警告
|
||
ShowSelfConnectionWarning(hitObject);
|
||
}
|
||
|
||
// 检查堆叠数量限制
|
||
if (enableStacking && maxStackCount > 0 && IsStackLimitReached(hitObject))
|
||
{
|
||
// 达到堆叠限制的接口仍然可以吸附,但会显示警告
|
||
ShowStackLimitWarning(hitObject);
|
||
}
|
||
|
||
// 计算鼠标位置与物体中心的距离
|
||
Vector3 objectCenter = GetObjectCenter(hitObject);
|
||
float distance = Vector3.Distance(GetMouseWorldPosition(), objectCenter);
|
||
|
||
if (distance <= snapDistance)
|
||
{
|
||
// 设置吸附目标
|
||
snapTarget = hitObject;
|
||
|
||
// 高亮显示可吸附的物体
|
||
HighlightSnapTarget(snapTarget);
|
||
}
|
||
}
|
||
}
|
||
|
||
Vector3 GetSnapPoint(RaycastHit hit)
|
||
{
|
||
if (!enableSnapping)
|
||
return hit.point;
|
||
|
||
GameObject hitObject = hit.collider.gameObject;
|
||
Vector3 objectCenter = GetObjectCenter(hitObject);
|
||
|
||
// 检查是否在吸附距离内
|
||
float distance = Vector3.Distance(hit.point, objectCenter);
|
||
if (distance <= snapDistance)
|
||
{
|
||
return objectCenter;
|
||
}
|
||
|
||
return hit.point;
|
||
}
|
||
|
||
Vector3 GetObjectCenter(GameObject obj)
|
||
{
|
||
if (obj == null) return Vector3.zero;
|
||
|
||
if (snapToColliderCenter)
|
||
{
|
||
Collider collider = obj.GetComponent<Collider>();
|
||
if (collider != null)
|
||
{
|
||
return collider.bounds.center;
|
||
}
|
||
}
|
||
|
||
if (snapToTransformCenter)
|
||
{
|
||
return obj.transform.position;
|
||
}
|
||
|
||
// 默认使用碰撞体中心
|
||
Collider defaultCollider = obj.GetComponent<Collider>();
|
||
if (defaultCollider != null)
|
||
{
|
||
return defaultCollider.bounds.center;
|
||
}
|
||
|
||
// 如果都没有,使用变换位置
|
||
return obj.transform.position;
|
||
}
|
||
|
||
void HighlightSnapTarget(GameObject target)
|
||
{
|
||
if (target == null) return;
|
||
|
||
// 如果已经高亮了其他接口,先恢复它的颜色
|
||
if (currentlyHighlightedInterface != null && currentlyHighlightedInterface != target)
|
||
{
|
||
RestoreInterfaceColor(currentlyHighlightedInterface);
|
||
}
|
||
|
||
snapTargetRenderer = target.GetComponent<Renderer>();
|
||
if (snapTargetRenderer != null)
|
||
{
|
||
// 确保使用材质实例,避免影响其他对象
|
||
EnsureMaterialInstance(target);
|
||
|
||
// 记录原始颜色到字典中
|
||
if (!highlightedInterfaces.ContainsKey(target))
|
||
{
|
||
highlightedInterfaces[target] = snapTargetRenderer.material.color;
|
||
Debug.Log($"记录接口 {target.name} 的原始颜色: {snapTargetRenderer.material.color}");
|
||
}
|
||
|
||
// 设置高亮颜色
|
||
// snapTargetRenderer.material.color = snapHighlightColor;
|
||
Debug.Log($"设置接口 {target.name} 为吸附高亮颜色: {snapHighlightColor}");
|
||
|
||
// 更新当前高亮接口
|
||
currentlyHighlightedInterface = target;
|
||
isSnapTargetHighlighted = true;
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 确保使用材质实例,避免影响其他使用相同材质的对象
|
||
/// </summary>
|
||
void EnsureMaterialInstance(GameObject target)
|
||
{
|
||
if (target == null) return;
|
||
|
||
Renderer renderer = target.GetComponent<Renderer>();
|
||
if (renderer != null)
|
||
{
|
||
// 如果还没有记录原始材质,记录下来
|
||
if (!originalMaterials.ContainsKey(target))
|
||
{
|
||
originalMaterials[target] = renderer.sharedMaterial;
|
||
}
|
||
|
||
// 确保使用材质实例
|
||
if (renderer.sharedMaterial == renderer.material)
|
||
{
|
||
// 如果共享材质和实例材质相同,说明还没有创建实例
|
||
renderer.material = new Material(renderer.sharedMaterial);
|
||
Debug.Log($"为接口 {target.name} 创建材质实例");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 恢复接口的原始材质
|
||
/// </summary>
|
||
void RestoreOriginalMaterial(GameObject target)
|
||
{
|
||
if (target == null) return;
|
||
|
||
if (originalMaterials.ContainsKey(target))
|
||
{
|
||
Renderer renderer = target.GetComponent<Renderer>();
|
||
if (renderer != null)
|
||
{
|
||
// 恢复原始材质
|
||
renderer.sharedMaterial = originalMaterials[target];
|
||
Debug.Log($"恢复接口 {target.name} 的原始材质");
|
||
}
|
||
|
||
// 从字典中移除
|
||
originalMaterials.Remove(target);
|
||
}
|
||
}
|
||
void ClearSnapHighlight()
|
||
{
|
||
if (snapTargetRenderer != null && isSnapTargetHighlighted)
|
||
{
|
||
// snapTargetRenderer.material.color = snapTargetOriginalColor;
|
||
snapTargetRenderer = null;
|
||
isSnapTargetHighlighted = false;
|
||
}
|
||
snapTarget = null;
|
||
}
|
||
|
||
// 修改 FinalizeWire 方法,添加记录功能
|
||
void FinalizeWire()
|
||
{
|
||
if (currentWireObject != null)
|
||
{
|
||
currentWireObject.name = $"Wire_{System.DateTime.Now:yyyyMMddHHmmss}";
|
||
|
||
// 将连接点附加到连线对象
|
||
AttachConnectionPointsToWire(currentWireObject);
|
||
|
||
if (useCylinderWire)
|
||
{
|
||
FinalizeCylinderWire();
|
||
}
|
||
else
|
||
{
|
||
// 原有的LineRenderer最终化代码
|
||
FinalizeLineRendererWire();
|
||
}
|
||
}
|
||
|
||
currentWire = null;
|
||
currentWireObject = null;
|
||
}
|
||
/// <summary>
|
||
/// 最终化LineRenderer连线(原有的FinalizeWire内容)
|
||
/// </summary>
|
||
void FinalizeLineRendererWire()
|
||
{
|
||
// 这里放置原有的FinalizeWire方法中的LineRenderer相关代码
|
||
FinalizeWire();
|
||
// 包括添加到连线列表、添加WireData组件等
|
||
|
||
allWires.Add(currentWireObject);
|
||
|
||
if (addColliderToWires)
|
||
{
|
||
AddWireCollider(currentWire);
|
||
}
|
||
|
||
WireData data = currentWireObject.AddComponent<WireData>();
|
||
data.startPoint = startPoint;
|
||
data.endPoint = endPoint;
|
||
data.creationTime = System.DateTime.Now;
|
||
|
||
if (startInterfaceObject != null)
|
||
{
|
||
data.snapStartObject = startInterfaceObject;
|
||
}
|
||
|
||
if (endInterfaceObject != null)
|
||
{
|
||
data.snapEndObject = endInterfaceObject;
|
||
}
|
||
|
||
WireConnectionData connectionData = new WireConnectionData
|
||
{
|
||
startInterface = startInterfaceObject,
|
||
endInterface = endInterfaceObject
|
||
};
|
||
wireConnectionData[currentWireObject] = connectionData;
|
||
|
||
Debug.Log($"连线完成: {currentWireObject.name}");
|
||
}
|
||
// 修改 CancelDrawing 方法,确保正确清理
|
||
void CancelDrawing()
|
||
{
|
||
if (currentWireObject != null)
|
||
{
|
||
Destroy(currentWireObject);
|
||
}
|
||
|
||
RemoveUnfinishedConnectionPoints();
|
||
ClearSnapPreview();
|
||
ClearAllHighlights();
|
||
|
||
// 恢复所有接口的原始材质
|
||
List<GameObject> interfacesToRestore = new List<GameObject>(originalMaterials.Keys);
|
||
foreach (GameObject interfaceObj in interfacesToRestore)
|
||
{
|
||
if (interfaceObj != null)
|
||
{
|
||
RestoreOriginalMaterial(interfaceObj);
|
||
}
|
||
}
|
||
originalMaterials.Clear();
|
||
|
||
currentState = DrawingState.Idle;
|
||
currentWire = null;
|
||
currentWireObject = null;
|
||
|
||
currentStartInterface = null;
|
||
currentEndInterface = null;
|
||
startInterfaceObject = null;
|
||
endInterfaceObject = null;
|
||
|
||
Debug.Log("取消连线操作");
|
||
}
|
||
/// <summary>
|
||
/// 更新吸附点预览模型
|
||
/// </summary>
|
||
void UpdateSnapPreview()
|
||
{
|
||
if (snapPreviewPrefab == null) return;
|
||
|
||
// 如果有吸附目标,显示预览
|
||
if (snapTarget != null)
|
||
{
|
||
if (currentSnapPreview == null)
|
||
{
|
||
currentSnapPreview = Instantiate(snapPreviewPrefab);
|
||
currentSnapPreview.name = "SnapPreview";
|
||
currentSnapPreview.transform.localScale = Vector3.one * connectionPointScale * 0.8f;
|
||
|
||
// 设置为半透明
|
||
Renderer renderer = currentSnapPreview.GetComponent<Renderer>();
|
||
if (renderer != null)
|
||
{
|
||
Color color = renderer.material.color;
|
||
color.a = 0.5f;
|
||
renderer.material.color = color;
|
||
}
|
||
}
|
||
|
||
Vector3 snapPosition = GetObjectCenter(snapTarget);
|
||
currentSnapPreview.transform.position = snapPosition;
|
||
|
||
// 根据状态改变预览颜色
|
||
Renderer previewRenderer = currentSnapPreview.GetComponent<Renderer>();
|
||
if (previewRenderer != null)
|
||
{
|
||
// 如果尝试自连接,使用自连接警告颜色
|
||
if (currentState == DrawingState.SelectingEnd && IsSelfConnection(snapTarget))
|
||
{
|
||
previewRenderer.material.color = selfConnectionWarningColor;
|
||
}
|
||
// 如果达到堆叠限制,改变预览颜色
|
||
else if (enableStacking && maxStackCount > 0 && IsStackLimitReached(snapTarget))
|
||
{
|
||
previewRenderer.material.color = maxStackWarningColor;
|
||
}
|
||
else
|
||
{
|
||
// 恢复半透明颜色
|
||
Color color = previewRenderer.material.color;
|
||
color.a = 0.5f;
|
||
previewRenderer.material.color = color;
|
||
}
|
||
}
|
||
}
|
||
else if (currentSnapPreview != null)
|
||
{
|
||
// 没有吸附目标时隐藏预览
|
||
ClearSnapPreview();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除吸附点预览
|
||
/// </summary>
|
||
void ClearSnapPreview()
|
||
{
|
||
if (currentSnapPreview != null)
|
||
{
|
||
Destroy(currentSnapPreview);
|
||
currentSnapPreview = null;
|
||
}
|
||
}
|
||
|
||
void ConfigureLineRenderer(LineRenderer lr)
|
||
{
|
||
if (wireMaterial != null)
|
||
{
|
||
lr.material = wireMaterial;
|
||
}
|
||
else
|
||
{
|
||
// 使用默认材质
|
||
lr.material = new Material(Shader.Find("Sprites/Default"));
|
||
}
|
||
|
||
lr.startColor = wireColor;
|
||
lr.endColor = wireColor;
|
||
lr.startWidth = wireWidth;
|
||
lr.endWidth = wireWidth;
|
||
lr.useWorldSpace = true;
|
||
}
|
||
|
||
// 修复:改进的碰撞器添加方法
|
||
void AddWireCollider(LineRenderer lr)
|
||
{
|
||
if (lr.positionCount < 2)
|
||
{
|
||
Debug.LogWarning("连线点数不足,无法添加碰撞器");
|
||
return;
|
||
}
|
||
|
||
// 创建胶囊碰撞器而不是网格碰撞器,避免Convex Mesh错误
|
||
CreateCapsuleCollidersAlongLine(lr);
|
||
}
|
||
|
||
// 修复:使用胶囊碰撞器替代网格碰撞器
|
||
void CreateCapsuleCollidersAlongLine(LineRenderer lr)
|
||
{
|
||
// 获取连线上的所有点
|
||
Vector3[] positions = new Vector3[lr.positionCount];
|
||
lr.GetPositions(positions);
|
||
|
||
// 为连线的每个线段创建胶囊碰撞器
|
||
for (int i = 0; i < positions.Length - 1; i++)
|
||
{
|
||
Vector3 start = positions[i];
|
||
Vector3 end = positions[i + 1];
|
||
|
||
// 计算线段长度和方向
|
||
float distance = Vector3.Distance(start, end);
|
||
if (distance < 0.01f) continue; // 跳过太短的线段
|
||
|
||
Vector3 direction = (end - start).normalized;
|
||
|
||
// 创建胶囊碰撞器
|
||
CapsuleCollider capsule = currentWireObject.AddComponent<CapsuleCollider>();
|
||
|
||
// 设置胶囊碰撞器的方向和位置
|
||
capsule.direction = 2; // Z轴方向
|
||
capsule.height = distance;
|
||
capsule.radius = wireWidth / 2;
|
||
|
||
// 计算胶囊的位置和旋转
|
||
capsule.center = start + direction * distance / 2;
|
||
|
||
// 设置胶囊的方向
|
||
if (direction != Vector3.zero)
|
||
{
|
||
capsule.transform.rotation = Quaternion.LookRotation(direction);
|
||
}
|
||
|
||
capsule.isTrigger = true;
|
||
}
|
||
}
|
||
|
||
// 修复:改进的鼠标位置获取方法
|
||
Vector3 GetMouseWorldPosition()
|
||
{
|
||
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
|
||
RaycastHit hit;
|
||
|
||
// 优先使用吸附目标的位置
|
||
if (snapTarget != null)
|
||
{
|
||
return GetObjectCenter(snapTarget);
|
||
}
|
||
|
||
// 其次使用射线击中的位置
|
||
if (Physics.Raycast(ray, out hit, Mathf.Infinity, snapLayers))
|
||
{
|
||
// 检查击中的物体是否有碰撞体
|
||
if (requireColliderForConnection && !HasCollider(hit.collider.gameObject))
|
||
{
|
||
// 如果没有碰撞体,继续寻找其他点
|
||
return FindAlternativePosition(ray);
|
||
}
|
||
|
||
return GetSnapPoint(hit);
|
||
}
|
||
|
||
// 如果没有击中任何物体,使用默认平面
|
||
return FindAlternativePosition(ray);
|
||
}
|
||
|
||
// 寻找替代位置(当没有碰撞体时)
|
||
Vector3 FindAlternativePosition(Ray ray)
|
||
{
|
||
// 尝试在默认平面上寻找位置
|
||
Plane defaultPlane = new Plane(Vector3.up, Vector3.zero);
|
||
float enter;
|
||
if (defaultPlane.Raycast(ray, out enter))
|
||
{
|
||
return ray.GetPoint(enter);
|
||
}
|
||
|
||
// 最后使用射线上的一个点
|
||
return ray.origin + ray.direction * 10f;
|
||
}
|
||
|
||
// 公共方法:开始新连线
|
||
public void StartNewWire()
|
||
{
|
||
if (currentState != DrawingState.Idle)
|
||
{
|
||
CancelDrawing();
|
||
}
|
||
currentState = DrawingState.SelectingStart;
|
||
}
|
||
|
||
// 公共方法:设置吸附目标(用于编程控制)
|
||
public void SetSnapTarget(GameObject target)
|
||
{
|
||
if (enableSnapping && target != null)
|
||
{
|
||
// 检查目标是否有碰撞体
|
||
if (requireColliderForConnection && !HasCollider(target))
|
||
{
|
||
Debug.LogWarning($"目标物体 {target.name} 没有碰撞体,无法设置为吸附目标");
|
||
return;
|
||
}
|
||
|
||
snapTarget = target;
|
||
HighlightSnapTarget(target);
|
||
}
|
||
}
|
||
|
||
// 公共方法:清除吸附目标
|
||
public void ClearSnapTarget()
|
||
{
|
||
ClearSnapHighlight();
|
||
}
|
||
|
||
// 公共方法:检查物体是否可以连线
|
||
public bool CanConnectToObject(GameObject obj)
|
||
{
|
||
if (obj == null) return false;
|
||
|
||
// 如果不需要碰撞体,任何物体都可以连线
|
||
if (!requireColliderForConnection) return true;
|
||
|
||
// 检查物体是否有碰撞体
|
||
return HasCollider(obj);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查接口是否可以接受新连接点(考虑堆叠限制和自连接)
|
||
/// </summary>
|
||
public bool CanInterfaceAcceptConnection(GameObject targetInterface)
|
||
{
|
||
if (targetInterface == null) return true;
|
||
|
||
// 检查自连接
|
||
if (IsSelfConnection(targetInterface))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
// 检查堆叠限制
|
||
if (!enableStacking || maxStackCount <= 0) return true;
|
||
|
||
return !IsStackLimitReached(targetInterface);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取接口上所有连接点的位置信息
|
||
/// </summary>
|
||
public List<Vector3> GetConnectionPointsOnInterface(GameObject targetInterface)
|
||
{
|
||
List<Vector3> positions = new List<Vector3>();
|
||
|
||
if (interfaceStacks.ContainsKey(targetInterface))
|
||
{
|
||
foreach (GameObject connectionPoint in interfaceStacks[targetInterface])
|
||
{
|
||
if (connectionPoint != null)
|
||
{
|
||
positions.Add(connectionPoint.transform.position);
|
||
}
|
||
}
|
||
}
|
||
|
||
return positions;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取接口上的连接点数量
|
||
/// </summary>
|
||
public int GetConnectionPointCountOnInterface(GameObject targetInterface)
|
||
{
|
||
return GetStackCountForInterface(targetInterface);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取接口的剩余可用连接点数量
|
||
/// </summary>
|
||
public int GetRemainingConnectionSlots(GameObject targetInterface)
|
||
{
|
||
if (!enableStacking || maxStackCount <= 0) return int.MaxValue;
|
||
|
||
int currentCount = GetStackCountForInterface(targetInterface);
|
||
return Mathf.Max(0, maxStackCount - currentCount);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置特定接口的最大堆叠数量(覆盖全局设置)
|
||
/// </summary>
|
||
public void SetInterfaceMaxStackCount(GameObject targetInterface, int maxCount)
|
||
{
|
||
// 这里可以扩展为每个接口有不同的最大堆叠数量
|
||
// 目前使用全局设置,但保留接口用于未来扩展
|
||
Debug.Log($"接口 {targetInterface?.name} 最大堆叠数量请求设置为 {maxCount},当前使用全局设置: {maxStackCount}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除特定接口上的所有连接点
|
||
/// </summary>
|
||
public void ClearConnectionPointsOnInterface(GameObject targetInterface)
|
||
{
|
||
if (interfaceStacks.ContainsKey(targetInterface))
|
||
{
|
||
// 创建副本,避免在遍历时修改集合
|
||
List<GameObject> pointsToRemove = new List<GameObject>(interfaceStacks[targetInterface]);
|
||
foreach (GameObject connectionPoint in pointsToRemove)
|
||
{
|
||
if (connectionPoint != null)
|
||
{
|
||
DeleteConnectionPoint(connectionPoint);
|
||
}
|
||
}
|
||
|
||
interfaceStacks.Remove(targetInterface);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置高亮功能开启/关闭
|
||
/// </summary>
|
||
public void SetHighlightEnabled(bool enabled)
|
||
{
|
||
enableHighlight = enabled;
|
||
|
||
if (!enabled)
|
||
{
|
||
// 如果禁用高亮,立即停止所有高亮效果
|
||
if (currentHighlightCoroutine != null)
|
||
{
|
||
StopCoroutine(currentHighlightCoroutine);
|
||
currentHighlightCoroutine = null;
|
||
}
|
||
|
||
// 恢复所有高亮物体的颜色
|
||
ClearAllHighlights();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 切换高亮功能状态
|
||
/// </summary>
|
||
public void ToggleHighlight()
|
||
{
|
||
SetHighlightEnabled(!enableHighlight);
|
||
Debug.Log($"点击高亮效果: {(enableHighlight ? "开启" : "关闭")}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置高亮颜色
|
||
/// </summary>
|
||
public void SetHighlightColor(Color color)
|
||
{
|
||
clickHighlightColor = color;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置高亮持续时间
|
||
/// </summary>
|
||
public void SetHighlightDuration(float duration)
|
||
{
|
||
highlightDuration = Mathf.Max(0.1f, duration);
|
||
}
|
||
} |