当前位置: 首页 > news >正文

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坐标转换解决方案。通过清晰的数学实现和丰富的可视化工具,它大大简化了空间映射相关的开发工作。无论是游戏开发、交互设计还是数据可视化,这个组件都能发挥重要作用。

相比之前介绍的线性映射组件,这个平面映射版本提供了更全面的空间转换能力,适合需要处理更复杂空间关系的项目。开发者可以根据实际需求选择使用,或者将两者结合实现更高级的空间映射系统。

Demo下载地址

http://www.dtcms.com/a/94765.html

相关文章:

  • 第十二篇《火攻篇》:一把火背后的战争哲学与生存智慧
  • CentOS(最小化)安装之后,快速搭建Docker环境
  • 设计模式(创建型)-建造者模式
  • 《Python实战进阶》No36: 使用 Hugging Face 构建 NLP 模型
  • 【数据库事务、消息队列事务、Redis 事务、Spring 事务 详细分析】
  • 【新手初学】读取服务器敏感文件数据
  • Scavenge算法的优缺点问题
  • K8S学习之基础五十八:部署nexus服务
  • Android 问真八字-v2.1.7[看八字APP]
  • 系统调用 与 中断
  • 【零基础入门】一篇掌握Python中的字典(创建、访问、修改、字典方法)【详细版】
  • 数据结构之优先级队列
  • 【SQL Server数据库备份详细教程】
  • SpringSecurity Web安全配置:HttpSecurity与WebSecurityConfigurerAdapter
  • 树莓派(4B)使用教程-小白之路(NO.1)
  • 游戏引擎学习第185天
  • 02. Linux嵌入式系统学习笔记(二)(编写C程序进行文件操作、模块化编程makefile的使用)
  • 3.28日职001:大阪樱花vs浦和红钻,樱花攻守失衡,红钻有望全取三分
  • 解决Cubemx生产的 .ioc文件不能外部打开的方法
  • 格力智造的十年进击
  • 【AI学习】人工神经网络
  • Qt MSVC2017连接mysql数据库
  • 单纯形法详解
  • uniapp uni-swipe-action滑动内容排版改造
  • STM32F103_LL库+寄存器学习笔记09 - DMA串口接收与DMA串口发送,串口接收空闲中断
  • 软件需求未明确非功能性指标(如并发量)的后果
  • 聚势赋能:“人工智能+”激活高质量发展动能与生成式人工智能(GAI)认证的新机遇
  • IP 分片重组与 TCP 会话重组
  • EXPLAIN 计划中 filtered 含义及作用解析
  • stc8g1k08a软件SPI点亮屏幕MD144-QQVGA14P-01-V01(ILI9163C)测试