Unity平面映射计算器:MappingCalculate_Plane组件深度解析
概述
MappingCalculate_Plane是一个强大的Unity组件,它能够将3D空间中的任意点投影到指定平面上,并计算出该点在平面局部坐标系中的2D坐标。这个组件非常适合需要将3D位置转换为2D平面坐标的各种应用场景。
效果:
核心功能
- 3D到2D的平面投影:将任意参考点投影到定义的平面上
- 实时坐标转换:自动计算投影点在平面局部坐标系中的(x,y)值
- 事件通知系统:当投影点位置变化时触发事件
- 可视化调试:内置编辑器辅助工具,直观显示投影关系
技术实现解析
平面投影算法
核心投影算法在PlanarMapping方法中实现:
public Vector3 PlanarMapping(Vector3 planeCenter, Vector3 currentPoint)
{Vector3 normal = transform.up; // 采用自身 transform 的 up 方向作为投影平面法线// 1. 将点投影到平面上Vector3 projectedPos = currentPoint - Vector3.Dot(currentPoint - planeCenter, normal) * normal;// 2. 转换为平面局部坐标Vector3 localOffset = projectedPos - planeCenter;value.x = Vector3.Dot(localOffset, transform.right); // X轴分量value.y = Vector3.Dot(localOffset, transform.forward); // Y轴分量onValueChanged?.Invoke(value);return projectedPos;
}
这个算法分为两个关键步骤:
-
空间投影:使用向量点积将3D点垂直投影到平面上
-
坐标转换:将投影点转换为平面局部2D坐标
实时更新机制
组件通过Update和UpdateMapping方法实现自动更新:
private void Update()
{UpdateMapping();
}public void UpdateMapping()
{if (referencePoint){// 检测参考点位置变化if (lastPosition == Vector3.zero)lastPosition = referencePoint.transform.position;if (referencePoint.transform.position != lastPosition){mappedPosition = PlanarMapping(transform.position, referencePoint.position);}lastPosition = referencePoint.transform.position;// 更新投影点位置if (projectedPoint)projectedPoint.position = mappedPosition;}
}
编辑器可视化
组件提供了丰富的场景视图可视化工具:
public void OnDrawGizmosSelected()
{// 绘制平面网格Vector3 planeCenter = transform.position;Vector3 right = transform.right;Vector3 forward = transform.forward;Gizmos.color = Color.black;int gridSize = 5;float cellSize = 0.1f;// 绘制网格线for (int i = -gridSize; i <= gridSize; i++){// 水平线Vector3 startH = planeCenter + right * (i * cellSize) - forward * (gridSize * cellSize);Vector3 endH = planeCenter + right * (i * cellSize) + forward * (gridSize * cellSize);Gizmos.DrawLine(startH, endH);// 垂直线Vector3 startV = planeCenter + forward * (i * cellSize) - right * (gridSize * cellSize);Vector3 endV = planeCenter + forward * (i * cellSize) + right * (gridSize * cellSize);Gizmos.DrawLine(startV, endV);}// 绘制投影关系if (referencePoint){Gizmos.color = Color.white;Gizmos.DrawLine(referencePoint.position, mappedPosition);Gizmos.DrawSphere(mappedPosition, 0.01f);Handles.Label(mappedPosition, value.ToString());}
}
自定义编辑器扩展
组件还包含了专门的编辑器脚本,增强了场景中的交互体验:
[CustomEditor(typeof(MappingCalculate_Plane))]
public class MappingCalculate_PlaneEditor : Editor
{private void OnSceneGUI(){MappingCalculate_Plane script = (MappingCalculate_Plane)target;if (script.referencePoint){// 添加可拖动的位置手柄EditorGUI.BeginChangeCheck();Vector3 newReferencePos = Handles.PositionHandle(script.referencePoint.position, Quaternion.identity);if (EditorGUI.EndChangeCheck()){Undo.RecordObject(script.referencePoint, "Move Reference Point");script.referencePoint.position = newReferencePos;}// 实时更新投影script.UpdateMapping();}}
}
实际应用场景
-
VR/AR交互:将3D手势位置映射到2D控制平面
-
游戏UI:在3D空间中创建动态的2D交互区域
-
建筑可视化:将3D模型位置转换为平面图坐标
-
动画控制:基于平面坐标控制角色或物体的行为
-
物理模拟:实现平面约束的运动系统
使用指南
1.将组件添加到GameObject上,该对象的transform定义了投影平面
2.设置referencePoint为需要投影的3D点
3.可选设置projectedPoint来可视化投影结果
4.通过onValueChanged事件监听2D坐标变化
事件系统
组件提供了MappingCalculatePanelEvent事件:
[Serializable]
public class MappingCalculatePanelEvent : UnityEvent<Vector2> { }[SerializeField]
private MappingCalculatePanelEvent m_OnValueChanged = new MappingCalculatePanelEvent();
public MappingCalculatePanelEvent onValueChanged { get { return m_OnValueChanged; } set { m_OnValueChanged = value; }
}
开发者可以通过Inspector绑定事件响应,或在代码中动态添加监听器。
总结
MappingCalculate_Plane组件为Unity开发者提供了一种高效可靠的3D到2D坐标转换解决方案。通过清晰的数学实现和丰富的可视化工具,它大大简化了空间映射相关的开发工作。无论是游戏开发、交互设计还是数据可视化,这个组件都能发挥重要作用。
相比之前介绍的线性映射组件,这个平面映射版本提供了更全面的空间转换能力,适合需要处理更复杂空间关系的项目。开发者可以根据实际需求选择使用,或者将两者结合实现更高级的空间映射系统。