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

【UnityEditor扩展】如何在 Unity 中创建棱柱体(用作VR安全区检测),同时在编辑器插件中实现与撤销/恢复功能

Unity 编辑器扩展:3D 空间中绘制安全区棱柱体(含撤销/恢复/保存/读取)

在虚拟现实(VR)和增强现实(AR)开发中,安全区是保障用户安全的重要组成部分。通过精确控制用户活动范围,可以避免用户与虚拟环境中的物体发生碰撞,确保舒适的体验。在本篇博客中,我们将实现一个 Unity 编辑器插件,用来 在 3D 空间中交互式绘制安全区棱柱体,并支持撤销/恢复、保存/读取功能。

功能概述

主要功能:

  1. 在 XZ 平面中绘制闭合路径:用户通过鼠标点击在 Scene 视图中绘制安全区的边界。

  2. 设置高度范围:可以定义每个安全区的起始高度和结束高度,生成棱柱体。

在这里插入图片描述

  1. 撤销与恢复:支持撤销上一个绘制点,并恢复已撤销的点。

  2. 保存与加载:用户可以将绘制的数据保存为 JSON 格式,并从文件中加载。

  3. 生成 Mesh 与 Collider:通过绘制的点生成对应的 Mesh 和 MeshCollider,作为安全区的碰撞检测区域。
    在这里插入图片描述

应用场景

  • XR 项目开发:在 VR 或 AR 环境中,安全区用于避免用户与虚拟物体发生碰撞或越界。
  • 游戏开发:某些游戏场景中需要限制玩家活动区域,例如在竞技场或战斗区域内定义活动边界。
  • 室内定位与导航:AR 导航应用中,为了确保用户的安全,通常会设置一个虚拟边界。

编辑器扩展插件实现

本教程将介绍如何使用 Unity 编辑器扩展功能,在 3D 空间中绘制一个安全区的棱柱体,并支持实时显示与编辑。

插件结构与设计

插件的核心功能是基于 EditorWindowSceneView 进行实现。我们将创建一个编辑器窗口,通过点击绘制点生成一个闭合的多边形,并根据用户设定的起始高度和结束高度生成棱柱体。


public class LineDrawingTool : EditorWindow
{

    [MenuItem("Tools/线条绘制工具")]
    public static void ShowWindow() { ... }

    private void OnGUI() { ... } // 工具窗口 UI
    private void OnSceneGUI(SceneView sceneView) { ... } // Scene 绘制
    private void GeneratePrismMesh() { ... } // 生成 Mesh
    private void SaveData() { ... } // 保存数据
    private void LoadData() { ... } // 加载数据
}

编辑器窗口 UI

OnGUI 方法中,我们将使用 Unity 的 GUI 系统来构建一个简洁易用的界面。界面包括:

  • 开始/结束绘制:用户可以点击按钮开始绘制或结束当前绘制。
  • 撤销/恢复:支持撤销上一个点,并恢复已撤销的点。
  • 高度设置:输入框允许用户设置安全区的起始高度和结束高度。
  • 保存/加载:可以将绘制的数据保存为 JSON 文件,也可以从文件中加载数据。
  • 生成 Mesh:用户可以点击按钮生成 Mesh 和 MeshCollider。

以下是 OnGUI 方法的核心实现:

private void OnGUI()
{
    GUILayout.Space(10);
    EditorGUILayout.LabelField("安全区棱柱绘制工具", EditorStyles.boldLabel);

    // 绘制状态控制
    if (GUILayout.Button(isDrawing ? "结束绘制" : "开始绘制", GUILayout.Height(30)))
    {
        isDrawing = !isDrawing;
        SceneView.RepaintAll();
    }

    // 撤销/恢复功能
    EditorGUILayout.BeginHorizontal();
    GUI.enabled = points.Count > 0;
    if (GUILayout.Button("撤销", GUILayout.Height(25)))
    {
        // 撤销上一个点
    }
    GUI.enabled = undoStack.Count > 0;
    if (GUILayout.Button("恢复", GUILayout.Height(25)))
    {
        // 恢复上次撤销的点
    }
    GUI.enabled = true;
    EditorGUILayout.EndHorizontal();

    // 高度设置
    EditorGUILayout.LabelField("高度范围", EditorStyles.boldLabel);
    float newStartHeight = EditorGUILayout.FloatField("起始高度", startHeight);
    float newEndHeight = EditorGUILayout.FloatField("结束高度", endHeight);
    if (!Mathf.Approximately(newStartHeight, startHeight) || !Mathf.Approximately(newEndHeight, endHeight))
    {
        startHeight = newStartHeight;
        endHeight = newEndHeight;
        SceneView.RepaintAll();
    }

    // 保存与读取
    if (GUILayout.Button("保存绘制数据"))
    {
        SaveData();
    }
    if (GUILayout.Button("读取绘制数据"))
    {
        LoadData();
    }
}

绘制与生成 Mesh

绘制路径的过程中,我们使用了 SceneView 中的 OnSceneGUI 方法实时监听鼠标输入,并在视图中绘制路径线条和当前点。

在用户设置好高度后,我们将顶面和底面按顶点生成三角形,侧面通过连接相邻的顶点来构建。

private void GeneratePrismMesh()
{
    // 使用顶点生成顶面、底面和侧面
    Mesh mesh = new Mesh();
    mesh.vertices = vertices.ToArray();
    mesh.triangles = triangles.ToArray();
    mesh.RecalculateNormals();

    // 创建 GameObject 和 MeshCollider
    GameObject prism = new GameObject("SafeZone_Prism");
    prism.AddComponent<MeshFilter>().sharedMesh = mesh;
    prism.AddComponent<MeshRenderer>().sharedMaterial = ...;
    prism.AddComponent<MeshCollider>().sharedMesh = mesh;
}

数据保存与加载

为了持久化绘制的数据,我们将其保存为 JSON 格式。这使得用户可以方便地保存并恢复绘制的安全区。

private void SaveData()
{
    LineDrawingData data = new LineDrawingData { points = points, startHeight = startHeight, endHeight = endHeight };
    string json = JsonUtility.ToJson(data, true);
    File.WriteAllText(path, json);
}

private void LoadData()
{
    string json = File.ReadAllText(path);
    LineDrawingData data = JsonUtility.FromJson<LineDrawingData>(json);
    points = data.points;
    startHeight = data.startHeight;
    endHeight = data.endHeight;
    SceneView.RepaintAll();
}

可扩展性与优化建议

这个插件提供了一个基础的框架,可以根据具体需求进一步扩展与优化:

  • 支持多区域绘制:可以支持多个安全区的绘制与管理。
  • 实时网格更新:在编辑过程中实时更新 Mesh 的预览。
  • 吸附网格与参考线:为绘制提供网格对齐和参考辅助线。
  • 导出为 ScriptableObject:将绘制的安全区作为资源保存,便于复用。

结论

通过本教程,你已经掌握了如何在 Unity 编辑器中创建一个交互式的安全区棱柱体绘制工具,并能够实现撤销、恢复、保存与读取功能。这个插件不仅可以帮助开发者快速创建安全区,还能方便地管理和重用已有的区域设置。

希望这篇博客能帮助你提高开发效率。如果你有其他问题或改进建议,欢迎在评论区留言交流!


源码与示例项目

项目源码可以通过以下链接获取(或留言):源码地址

后续还会分享更多关于 Unity 编辑器工具开发、XR 项目优化等内容,敬请关注!

相关文章:

  • flink Shuffle的总结
  • [ctfshow web入门] web19
  • 第四讲:类与对象(下)
  • 如何在React中集成 PDF.js?构建支持打印下载的PDF阅读器详解
  • mapbox基础,加载栅格图片到地图
  • QMT实盘代码案例教学:etf全球配置策略
  • 深入理解Java性能调优与JVM底层机制
  • 柯尼卡美能达CA-410-CA-VP427 P427
  • 从 “单打独斗” 到 “生态共赢” 跨境货源池的协同增长逻辑
  • 摄像头模块对焦方式的类型
  • Java基础 4.7
  • 基于Python的二手房数据挖掘与可视化深度分析
  • STM32单片机入门学习——第22节: [7-2] AD单通道AD多通道
  • AutoAgent: 香港大学开源的AI智能体框架
  • ARM-IIC
  • #简易线程池...实现原理
  • 从零开始的图论讲解(1)——图的概念,图的存储,图的遍历与图的拓扑排序
  • ubuntu 20.04 编译和运行A-LOAM
  • std::async 和 std::thread 的主要区别
  • 使用Vue、Nodejs以及websocket搭建一个简易聊天室
  • 南宁做网站开发的公司有哪些/抖音推广方案
  • 做网站流量怎么赚钱吗/网站优化推广哪家好
  • 电脑搭建网站需要空间/微信公众号的推广
  • 怎么查网站有没有做404/全球搜索引擎排行榜
  • 企业信用网查询/东莞seo网站排名优化公司
  • 网站UI怎么做/口碑营销有哪些