public static void OutputShipLaunchersToFlatBuffer()
    {
        // 所有飞船Prefab的目录
        List <string> prefabDirPath = new List <string>();

        prefabDirPath.Add(Application.dataPath + "/Artwork/Spacecraft/Ships_Player/Prefabs");
        prefabDirPath.Add(Application.dataPath + "/Artwork/Spacecraft/Ships_Enemy/Prefabs");
        prefabDirPath.Add(Application.dataPath + "/Artwork/Spacecraft/Ships_NPC/Prefabs");
        prefabDirPath.Add(Application.dataPath + "/Artwork/Spacecraft/Ships_device/Prefabs");

        // 找到Prefab那一列
        // 打开Excel文件

        /*ExcelWriter excelWriter = new ExcelWriter();
         * excelWriter.OpenExcel(Application.dataPath + "/../../eternity_configurations/share/data/model.xlsx");
         * excelWriter.OpenSheet("Sheet1");*/

        string    csvPath   = Application.dataPath + "/../../eternity_configurations/share/data/csv/model.csv";
        string    sheetName = "model";
        CSVReader csvReader = new CSVReader();

        csvReader.OpenCSV(csvPath, sheetName);

        // 遍历所有Prefab, 写入FlatBuffer文件
        MyLauncher myLauncher = new MyLauncher();

        myLauncher.LauncherVOList = new List <MyLauncherVO>();

        List <string> errorList = new List <string>();

        foreach (string dirPath in prefabDirPath)
        {
            Debug.Log(dirPath);
            List <string> prefabPathList = GetAllFilesWithExtension(dirPath, "prefab");
            for (int iPath = 0; iPath < prefabPathList.Count; iPath++)
            {
                // List<MyLauncherVO> launcherList = GetShipLauncher(excelWriter, FileUtility.AbsolutePathToRelativeDataPath(prefabPathList[iPath]), errorList);
                List <MyLauncherVO> launcherList = GetShipLauncher(csvReader, FileUtility.AbsolutePathToRelativeDataPath(prefabPathList[iPath]), errorList);
                if (launcherList != null)
                {
                    myLauncher.LauncherVOList.AddRange(launcherList);
                }
            }
        }

        TransMyDataToFlatBuffer(myLauncher);

        csvReader.CloseCsv();

        // Read
        string fileName = Application.dataPath + "\\..\\..\\product\\server\\resource\\flatbuffers\\spacecraft_launcher.bytes";

        fileName.Replace("/", "\\");
        byte[]     fileData   = File.ReadAllBytes(fileName);
        ByteBuffer byteBuffer = new ByteBuffer(fileData);

        TestDataRead(byteBuffer);


        // Display Dialog
        StringBuilder errorInfo = new StringBuilder();

        foreach (string error in errorList)
        {
            errorInfo.Append(error);
            errorInfo.Append('\n');
        }

        if (errorList.Count != 0)
        {
            EditorUtility.DisplayDialog("某些飞船的技能释放点信息未导出", errorInfo.ToString(), "朕知道了");
        }

        string Message = string.Format("已经把所有飞船的技能释放点信息导出至 {0}"
                                       , Application.dataPath + "\\..\\..\\product\\server\\resource\\flatbuffers\\spacecraft_launcher.bytes");

        fileName.Replace("/", "\\");
        EditorUtility.DisplayDialog("导出完成", Message, "朕知道了");

        if (Application.isBatchMode)
        {
            EditorApplication.Exit(0);
        }
    }
    /// <summary>
    /// 把自定义的数据格式转换成Flatbuffer
    /// </summary>
    /// <param name="launcherVOList"></param>
    public static void TransMyDataToFlatBuffer(MyLauncher myLauncher)
    {
        FlatBufferBuilder builder = new FlatBufferBuilder(1);

        List <MyLauncherVO> launcherVOList = myLauncher.LauncherVOList;
        bool haveLauncherVO = launcherVOList != null && launcherVOList.Count > 0;

        // LauncherVO
        Offset <LauncherVO>[] launcherVOs = haveLauncherVO ? new Offset <LauncherVO> [launcherVOList.Count] : null;
        if (haveLauncherVO)
        {
            // 这里使用反序的原因是, 服务器读出来的顺序与我写入的顺序是相反的
            // FlatBuffer的内部实现没看明白. 先直接写成反序了
            for (int iLauncherVO = launcherVOList.Count - 1; iLauncherVO >= 0; iLauncherVO--)
            {
                List <MyLauncherMergeVO>   mergeList = launcherVOList[iLauncherVO].LauncherMergeVOList;
                Offset <LauncherMergeVO>[] mergeVOs  = new Offset <LauncherMergeVO> [mergeList.Count];
                for (int iMerge = mergeList.Count - 1; iMerge >= 0; iMerge--)
                {
                    List <MyPointInfoVO> pointList = mergeList[iMerge].PointInfoVOList;
                    // pointInfoVo
                    LauncherMergeVO.StartPointInfoArrayVector(builder, pointList.Count);
                    for (int iPoint = pointList.Count - 1; iPoint >= 0; iPoint--)
                    {
                        Vector3 pos = pointList[iPoint].Position;
                        Vector3 dir = pointList[iPoint].Direction;
                        pointInfoVo.CreatepointInfoVo(builder, pos.x, pos.z, pos.y, dir.z, dir.y, dir.x);
                    }
                    VectorOffset pointVector = builder.EndVector();

                    // MergeVO
                    LauncherMergeVO.StartLauncherMergeVO(builder);
                    LauncherMergeVO.AddPointType(builder, mergeList[iMerge].PointType);
                    LauncherMergeVO.AddPointInfoArray(builder, pointVector);
                    mergeVOs[iMerge] = LauncherMergeVO.EndLauncherMergeVO(builder);
                }
                VectorOffset mergeVOVector = LauncherMergeVO.CreateSortedVectorOfLauncherMergeVO(builder, mergeVOs);

                // LauncherVO
                LauncherVO.StartLauncherVO(builder);
                LauncherVO.AddId(builder, launcherVOList[iLauncherVO].ID);
                LauncherVO.AddMergeArray(builder, mergeVOVector);
                launcherVOs[iLauncherVO] = LauncherVO.EndLauncherVO(builder);
            }
        }

        // Launcher
        VectorOffset launcherVOVector = haveLauncherVO ? LauncherVO.CreateSortedVectorOfLauncherVO(builder, launcherVOs) : new VectorOffset();

        Launcher.StartLauncher(builder);
        if (haveLauncherVO)
        {
            Launcher.AddData(builder, launcherVOVector);
        }
        Offset <Launcher> launcher = Launcher.EndLauncher(builder);

        // SpacecraftLauncher
        SpacecraftLauncher.StartSpacecraftLauncher(builder);
        SpacecraftLauncher.AddLauncher(builder, launcher);
        Offset <SpacecraftLauncher> spacecraft = SpacecraftLauncher.EndSpacecraftLauncher(builder);

        SpacecraftLauncher.FinishSpacecraftLauncherBuffer(builder, spacecraft);

        // Write To File
        using (MemoryStream stream = new MemoryStream(builder.DataBuffer.ToFullArray(), builder.DataBuffer.Position, builder.Offset))
        {
            byte[] data     = stream.ToArray();
            string fileName = Application.dataPath + "\\..\\..\\product\\server\\resource\\flatbuffers\\spacecraft_launcher.bytes";
            fileName.Replace("/", "\\");
            File.WriteAllBytes(fileName, data);
        }

        /*using (MemoryStream stream = new MemoryStream(builder.DataBuffer.ToFullArray(), builder.DataBuffer.Position, builder.Offset))
         * {
         *  byte[] data = stream.ToArray();
         *  string fileName = Application.dataPath + "\\..\\..\\data\\output\\flatBuffers\\server\\data\\spacecraft_launcher.bytes";
         *  fileName.Replace("/", "\\");
         *  File.WriteAllBytes(fileName, data);
         * }
         */
    }