Unity映射计算器:使用平面投影
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坐标转换解决方案。通过清晰的数学实现和丰富的可视化工具,它大大简化了空间映射相关的开发工作。无论是游戏开发、交互设计还是数据可视化,这个组件都能发挥重要作用。
相比之前介绍的线性映射组件,这个平面映射版本提供了更全面的空间转换能力,适合需要处理更复杂空间关系的项目。开发者可以根据实际需求选择使用,或者将两者结合实现更高级的空间映射系统。