using System.Collections.Generic; using UnityEngine; namespace UnityMoveIt2.Core { /// /// 可视化引擎 - 碰撞可视化部分 / Visualization Engine - Collision Visualization Part /// public partial class VisualizationEngine { #region Collision Fields [Header("碰撞可视化设置 / Collision Visualization Settings")] [SerializeField] private Color collisionColor = Color.red; [SerializeField] private Color warningColor = Color.yellow; [SerializeField] [Tooltip("碰撞透明度 / Collision Transparency")] private float collisionTransparency = 0.5f; [SerializeField] [Tooltip("警告距离(米) / Warning Distance (m)")] private float warningDistance = 0.1f; [SerializeField] [Tooltip("显示碰撞边界 / Show Collision Bounds")] private bool showCollisionBounds = true; private Dictionary collisionHighlights; private List activeCollisions; private Material collisionMaterial; private Material warningMaterial; #endregion #region Collision Initialization private void InitializeCollisionVisualization() { collisionHighlights = new Dictionary(); activeCollisions = new List(); // 创建碰撞材质 / Create collision materials collisionMaterial = CreateTransparentMaterial(collisionColor, collisionTransparency); warningMaterial = CreateTransparentMaterial(warningColor, collisionTransparency); Debug.Log("[VisualizationEngine] 碰撞可视化已初始化 / Collision visualization initialized"); } private Material CreateTransparentMaterial(Color color, float transparency) { Material mat = new Material(Shader.Find("Standard")); mat.SetFloat("_Mode", 3); // Transparent mode mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); mat.SetInt("_ZWrite", 0); mat.DisableKeyword("_ALPHATEST_ON"); mat.EnableKeyword("_ALPHABLEND_ON"); mat.DisableKeyword("_ALPHAPREMULTIPLY_ON"); mat.renderQueue = 3000; mat.color = new Color(color.r, color.g, color.b, transparency); return mat; } #endregion #region Collision Update private void UpdateCollisionVisualization() { // 更新碰撞高亮 / Update collision highlights UpdateActiveCollisionHighlights(); // 清理过期的碰撞高亮 / Clean up expired collision highlights CleanupInactiveCollisions(); } private void UpdateActiveCollisionHighlights() { foreach (var collision in activeCollisions) { if (!collisionHighlights.ContainsKey(collision.objectName)) { CreateCollisionHighlight(collision); } UpdateCollisionHighlight(collision); } } private void CreateCollisionHighlight(CollisionPair collision) { GameObject target = GameObject.Find(collision.objectName); if (target == null) return; GameObject highlight = new GameObject($"CollisionHighlight_{collision.objectName}"); highlight.transform.SetParent(collisionContainer.transform); // 复制目标的网格 / Copy target's mesh MeshFilter meshFilter = target.GetComponent(); if (meshFilter != null) { MeshFilter highlightMesh = highlight.AddComponent(); highlightMesh.mesh = meshFilter.mesh; MeshRenderer renderer = highlight.AddComponent(); renderer.material = collision.isWarning ? warningMaterial : collisionMaterial; } // 同步位置和旋转 / Sync position and rotation highlight.transform.position = target.transform.position; highlight.transform.rotation = target.transform.rotation; highlight.transform.localScale = target.transform.localScale; collisionHighlights[collision.objectName] = highlight; } private void UpdateCollisionHighlight(CollisionPair collision) { if (!collisionHighlights.ContainsKey(collision.objectName)) return; GameObject highlight = collisionHighlights[collision.objectName]; GameObject target = GameObject.Find(collision.objectName); if (target != null && highlight != null) { // 更新位置和旋转 / Update position and rotation highlight.transform.position = target.transform.position; highlight.transform.rotation = target.transform.rotation; highlight.transform.localScale = target.transform.localScale; // 更新材质 / Update material MeshRenderer renderer = highlight.GetComponent(); if (renderer != null) { renderer.material = collision.isWarning ? warningMaterial : collisionMaterial; } } } private void CleanupInactiveCollisions() { List toRemove = new List(); foreach (var kvp in collisionHighlights) { bool isActive = false; foreach (var collision in activeCollisions) { if (collision.objectName == kvp.Key) { isActive = true; break; } } if (!isActive) { toRemove.Add(kvp.Key); } } foreach (var key in toRemove) { if (collisionHighlights[key] != null) { Destroy(collisionHighlights[key]); } collisionHighlights.Remove(key); } } #endregion #region Public Collision Methods /// /// 高亮显示碰撞对象 / Highlight Collision Objects /// public void HighlightCollisions(List objectNames) { activeCollisions.Clear(); foreach (var name in objectNames) { activeCollisions.Add(new CollisionPair { objectName = name, isWarning = false, distance = 0f }); } UpdateCollisionVisualization(); } /// /// 显示碰撞警告 / Show Collision Warnings /// public void ShowCollisionWarnings(List proximities) { foreach (var proximity in proximities) { if (proximity.distance < warningDistance) { bool found = false; foreach (var collision in activeCollisions) { if (collision.objectName == proximity.objectName) { found = true; break; } } if (!found) { activeCollisions.Add(new CollisionPair { objectName = proximity.objectName, isWarning = true, distance = proximity.distance }); } } } UpdateCollisionVisualization(); } /// /// 清除碰撞可视化 / Clear Collision Visualization /// public void ClearCollisionVisualization() { activeCollisions.Clear(); foreach (var kvp in collisionHighlights) { if (kvp.Value != null) { Destroy(kvp.Value); } } collisionHighlights.Clear(); Debug.Log("[VisualizationEngine] 已清除碰撞可视化 / Cleared collision visualization"); } /// /// 设置碰撞对象列表 / Set Collision Objects List /// public void SetCollisionObjects(List collisions) { activeCollisions = new List(collisions); UpdateCollisionVisualization(); } #endregion #region Collision Gizmos private void DrawCollisionGizmos() { if (!showCollisionBounds) return; Gizmos.color = collisionColor; foreach (var collision in activeCollisions) { GameObject obj = GameObject.Find(collision.objectName); if (obj != null) { Bounds bounds = GetObjectBounds(obj); if (bounds.size != Vector3.zero) { Gizmos.DrawWireCube(bounds.center, bounds.size); } } } } private Bounds GetObjectBounds(GameObject obj) { Renderer renderer = obj.GetComponent(); if (renderer != null) { return renderer.bounds; } Collider collider = obj.GetComponent(); if (collider != null) { return collider.bounds; } return new Bounds(obj.transform.position, Vector3.zero); } #endregion } #region Collision Data Structures /// /// 碰撞对信息 / Collision Pair Information /// [System.Serializable] public class CollisionPair { public string objectName; public bool isWarning; public float distance; } /// /// 接近度信息 / Proximity Information /// [System.Serializable] public class ProximityInfo { public string objectName; public float distance; public Vector3 closestPoint; } #endregion }