unity场景数据导出到excel的实现

下面我将为你提供一个完整的示例,展示如何在 Unity 中实现从场景导出数据到 Excel 的功能。这个示例将涵盖你提到的所有步骤,包括创建编辑器窗口、查找场景中的对象、导出数据到 Excel 文件等。

1. 创建编辑器窗口

首先,创建一个名为 ExportData4Svr.cs 的文件,并放置在 Assembly-CSharp-Editor/Editor 目录下。以下是基本的代码结构:

using UnityEngine;
using UnityEditor;
using System.IO;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;

public class ExportData4Svr : EditorWindow
{
    [MenuItem("Tools/ExportData4Svr")]
    static void Export()
    {
        ExportData();
    }

    static void ExportData()
    {
        // 这里可以调用其他方法来获取数据并导出
        Dump();
    }

    public static void Dump()
    {
        // 相对路径表示的excel文件名
        string excelPath = "Assets/Resources/场景表.xls";

        // 创建工作簿
        HSSFWorkbook workBook = new HSSFWorkbook();
        ISheet sheet = workBook.CreateSheet("场景配置");

        // 创建表头
        IRow headerRow = sheet.CreateRow(0);
        headerRow.CreateCell(0).SetCellValue("地图宽度");
        headerRow.CreateCell(1).SetCellValue("地图高度");

        // 这里可以添加更多的列

        // 示例数据
        int mapWidth = 100; // 这里可以替换为实际的地图宽度
        int mapHeight = 100; // 这里可以替换为实际的地图高度

        // 创建数据行
        IRow dataRow = sheet.CreateRow(1);
        dataRow.CreateCell(0).SetCellValue(mapWidth);
        dataRow.CreateCell(1).SetCellValue(mapHeight);

        // 写入文件
        using (FileStream fs = new FileStream(excelPath, FileMode.Create, FileAccess.Write))
        {
            workBook.Write(fs);
        }

        workBook.Close();
        AssetDatabase.Refresh(); // 刷新资源
        Debug.Log("数据导出成功到: " + excelPath);
    }
}

2. 获取场景中的资源数据

ExportData 方法中,你可以添加代码来查找场景中的对象并获取它们的数据。以下是一个示例,展示如何查找特定类型的对象和根据名称查找对象:

static void ExportData()
{
    // 获取场景中的所有 Tree 类型的对象
    Component[] trees = GameObject.Find("SceneRoot").GetComponentsInChildren(typeof(Tree));
    foreach (var tree in trees)
    {
        Debug.Log("Found tree at position: " + tree.transform.position);
    }

    // 获取所有以 "water" 开头的材质
    GameObject terrain = GameObject.Find("SceneRoot");
    foreach (Transform child in terrain.transform)
    {
        Renderer render = child.gameObject.GetComponent<Renderer>();
        if (render != null)
        {
            foreach (var material in render.sharedMaterials)
            {
                if (material.name.StartsWith("water"))
                {
                    Debug.Log("Water position: " + child.gameObject.transform.position);
                }
            }
        }
    }

    // 继续调用 Dump 方法来导出数据
    Dump();
}

3. 使用 NPOI 库操作 Excel

确保你已经将 NPOI 库添加到 Unity 项目中。你可以通过 NuGet 或直接下载 NPOI 的 DLL 文件并放入 Assets/Plugins 目录。

4. 完整代码示例

将上述代码整合在一起,形成一个完整的 ExportData4Svr.cs 文件:

using UnityEngine;
using UnityEditor;
using System.IO;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;

public class ExportData4Svr : EditorWindow
{
    [MenuItem("Tools/ExportData4Svr")]
    static void Export()
    {
        ExportData();
    }

    static void ExportData()
    {
        // 获取场景中的所有 Tree 类型的对象
        Component[] trees = GameObject.Find("SceneRoot").GetComponentsInChildren(typeof(Tree));
        foreach (var tree in trees)
        {
            Debug.Log("Found tree at position: " + tree.transform.position);
        }

        // 获取所有以 "water" 开头的材质
        GameObject terrain = GameObject.Find("SceneRoot");
        foreach (Transform child in terrain.transform)
        {
            Renderer render = child.gameObject.GetComponent<Renderer>();
            if (render != null)
            {
                foreach (var material in render.sharedMaterials)
                {
                    if (material.name.StartsWith("water"))
                    {
                        Debug.Log("Water position: " + child.gameObject.transform.position);
                    }
                }
            }
        }

        // 调用 Dump 方法来导出数据
        Dump();
    }

    public static void Dump()
    {
        // 相对路径表示的excel文件名
        string excelPath = "Assets/Resources/场景表.xls";

        // 创建工作簿
        HSSFWorkbook workBook = new HSSFWorkbook();
        ISheet sheet = workBook.CreateSheet("场景配置");

        // 创建表头
        IRow headerRow = sheet.CreateRow(0);
        headerRow.CreateCell(0).SetCellValue("地图宽度");
        headerRow.CreateCell(1).SetCellValue("地图高度");
        headerRow.CreateCell(2).SetCellValue("树木数量");
        headerRow.CreateCell(3).SetCellValue("水体位置");

        // 示例数据
        int mapWidth = 100; // 这里可以替换为实际的地图宽度
        int mapHeight = 100; // 这里可以替换为实际的地图高度
        int treeCount = GameObject.Find("SceneRoot").GetComponentsInChildren<Tree>().Length;

        // 创建数据行
        IRow dataRow = sheet.CreateRow(1);
        dataRow.CreateCell(0).SetCellValue(mapWidth);
        dataRow.CreateCell(1).SetCellValue(mapHeight);
        dataRow.CreateCell(2).SetCellValue(treeCount);

        // 记录水体位置
        int waterRowIndex = 2; // 从第二行开始记录水体位置
        foreach (Transform child in GameObject.Find("SceneRoot").transform)
        {
            Renderer render = child.gameObject.GetComponent<Renderer>();
            if (render != null)
            {
                foreach (var material in render.sharedMaterials)
                {
                    if (material.name.StartsWith("water"))
                    {
                        IRow waterRow = sheet.CreateRow(waterRowIndex++);
                        waterRow.CreateCell(0).SetCellValue("水体位置");
                        waterRow.CreateCell(1).SetCellValue(child.gameObject.transform.position.x);
                        waterRow.CreateCell(2).SetCellValue(child.gameObject.transform.position.y);
                        waterRow.CreateCell(3).SetCellValue(child.gameObject.transform.position.z);
                    }
                }
            }
        }

        // 写入文件
        using (FileStream fs = new FileStream(excelPath, FileMode.Create, FileAccess.Write))
        {
            workBook.Write(fs);
        }

        workBook.Close();
        AssetDatabase.Refresh(); // 刷新资源
        Debug.Log("数据导出成功到: " + excelPath);
    }
}

代码说明

  1. 菜单项:通过 MenuItem 属性创建一个菜单项,点击后会调用 Export 方法。
  2. 导出数据:在 ExportData 方法中,首先查找场景中的所有 Tree 类型的对象,并记录它们的位置。然后查找所有以 “water” 开头的材质,并记录它们的位置。
  3. 写入 Excel:在 Dump 方法中,创建一个 Excel 工作簿,并在第一行写入表头。接着,写入地图的宽度、高度和树木数量。最后,记录水体的位置。
  4. 文件写入:使用 FileStream 将数据写入到指定路径的 Excel 文件中,并在完成后刷新 Unity 的资源管理器。

运行步骤

  1. 将上述代码保存到 ExportData4Svr.cs 文件中。
  2. 确保 NPOI 库已正确添加到 Unity 项目中。
  3. 在 Unity 编辑器中,点击菜单 Tools -> ExportData4Svr,运行导出功能。
  4. 检查 Assets/Resources/场景表.xls 文件,确认数据是否正确导出。

未来的扩展

  1. 支持更多数据类型

    • 敌人位置:可以添加代码来查找场景中的敌人对象,并记录它们的位置。
    • 可交互对象:查找所有可交互的对象(如门、开关等),并记录它们的状态和位置。
    • 资源点:如果有资源点(如矿石、树木等),可以记录它们的位置和类型。

    下面是一个示例,展示如何查找敌人对象并记录它们的位置:

    // 查找敌人对象
    Component[] enemies = GameObject.Find("SceneRoot").GetComponentsInChildren(typeof(Enemy));
    foreach (var enemy in enemies)
    {
        Debug.Log("Found enemy at position: " + enemy.transform.position);
    }
    
  2. 支持其他数据格式

    • 除了 Excel,你还可以考虑导出为 JSON 或 XML 格式,这样可以更方便地与其他系统进行集成。
    • 使用 JsonUtility 类可以轻松将数据序列化为 JSON 格式。

    示例代码(导出为 JSON):

    [System.Serializable]
    public class SceneData
    {
        public int mapWidth;
        public int mapHeight;
        public List<Vector3> waterPositions;
    }
    
    public static void ExportToJson()
    {
        SceneData sceneData = new SceneData
        {
            mapWidth = 100, // 替换为实际值
            mapHeight = 100, // 替换为实际值
            waterPositions = new List<Vector3>()
        };
    
        // 添加水体位置
        foreach (Transform child in GameObject.Find("SceneRoot").transform)
        {
            Renderer render = child.gameObject.GetComponent<Renderer>();
            if (render != null)
            {
                foreach (var material in render.sharedMaterials)
                {
                    if (material.name.StartsWith("water"))
                    {
                        sceneData.waterPositions.Add(child.gameObject.transform.position);
                    }
                }
            }
        }
    
        string json = JsonUtility.ToJson(sceneData, true);
        File.WriteAllText("Assets/Resources/场景数据.json", json);
        Debug.Log("数据导出成功到: Assets/Resources/场景数据.json");
    }
    
  3. 优化代码结构

    • 将数据导出逻辑分离到不同的方法中,以提高可读性和可维护性。
    • 使用数据结构(如类或结构体)来存储导出的数据,便于管理和扩展。

    示例代码(使用类来存储数据):

    [System.Serializable]
    public class TreeData
    {
        public Vector3 position;
    }
    
    [System.Serializable]
    public class WaterData
    {
        public Vector3 position;
    }
    
    public class SceneExportData
    {
        public int mapWidth;
        public int mapHeight;
        public List<TreeData> trees = new List<TreeData>();
        public List<WaterData> waters = new List<WaterData>();
    }
    
  4. 用户界面改进

    • 可以为导出功能添加更多的用户界面选项,例如选择导出格式、选择导出数据的类型等。
    • 使用 EditorGUILayout 类来创建更友好的编辑器界面。

    示例代码(简单的用户界面):

    private bool exportToExcel = true;
    private bool exportToJson = false;
    
    void OnGUI()
    {
        exportToExcel = EditorGUILayout.Toggle("导出到 Excel", exportToExcel);
        exportToJson = EditorGUILayout.Toggle("导出到 JSON", exportToJson);
    
        if (GUILayout.Button("导出数据"))
        {
            if (exportToExcel)
            {
                ExportData();
            }
            if (exportToJson)
            {
                ExportToJson();
            }
        }
    }
    

总结

通过以上的扩展和优化,你可以将 Unity 编辑器中的数据导出功能提升到一个新的水平。无论是支持更多的数据类型、导出格式,还是优化代码结构和用户界面,这些改进都将使得你的工具更加灵活和易用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你一身傲骨怎能输

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值