diff --git a/Assets/MindPowerSdk/EditorWindow/MapDataEditorWindow.cs b/Assets/MindPowerSdk/EditorWindow/MapDataEditorWindow.cs index 2dbb6e3..3ff73f3 100644 --- a/Assets/MindPowerSdk/EditorWindow/MapDataEditorWindow.cs +++ b/Assets/MindPowerSdk/EditorWindow/MapDataEditorWindow.cs @@ -78,9 +78,10 @@ namespace MindPowerSdk.Editor for (int i = 0; i < mapEntries.Count; i++) { EditorGUILayout.BeginHorizontal(); - mapEntries[i].mapName = EditorGUILayout.TextField("Map 名称", mapEntries[i].mapName); - mapEntries[i].resourceDataName = EditorGUILayout.TextField("资源名称", mapEntries[i].resourceDataName); - mapEntries[i].isSmoothing = EditorGUILayout.Toggle("对地形平滑处理", mapEntries[i].isSmoothing); + mapEntries[i].mapName = EditorGUILayout.TextField("Map 名称", mapEntries[i].mapName).Replace(".map", ""); + mapEntries[i].resourceDataName = EditorGUILayout.TextField("资源名称", mapEntries[i].resourceDataName) + .Replace(".obj", ""); + mapEntries[i].isSmoothing = EditorGUILayout.Toggle("对地形平滑处理", mapEntries[i].isSmoothing); if (GUILayout.Button("删除", GUILayout.Width(60))) { mapEntries.RemoveAt(i); @@ -176,9 +177,8 @@ namespace MindPowerSdk.Editor foreach (var entry in mapEntries) { // 拼接完整数据路径 - string mapDataPath = Path.Combine(mapDataFolder, entry.mapName); - string resourceDataPath = Path.Combine(resourceDataFolder, entry.resourceDataName); - + string mapDataPath = Path.Combine(mapDataFolder, entry.mapName + ".map"); + string resourceDataPath = Path.Combine(resourceDataFolder, entry.resourceDataName + ".obj"); // 读取地图数据 using FileStream fs = File.OpenRead(mapDataPath); BinaryReader reader = new BinaryReader(fs); @@ -190,9 +190,68 @@ namespace MindPowerSdk.Editor TerrainGenerator.GenTerrain(map, chunkSize, terrainMaterial, parent.transform, entry.mapName, entry.isSmoothing); Debug.Log($"生成地图:{entry.mapName}\n数据路径:{mapDataPath}\n资源路径:{resourceDataPath}"); + + CreateMapObject(resourceDataPath, map, parent.transform); } } + + void CreateMapObject(string objPath, MPMap map, Transform parent) + { + CSceneObjSet sceneObjSet = new CSceneObjSet(); + sceneObjSet.LoadBin("Assets/Resources/sceneobjinfo.bin"); + + SceneObjFile sceneObjFile = new SceneObjFile(); + sceneObjFile.Load(objPath); + string objName = Path.GetFileNameWithoutExtension(objPath); + GameObject root = new GameObject($"{objName}_SceneAssetsRoot"); + root.transform.SetParent(parent); + for (int y = 0; y < sceneObjFile.FileHeader.SectionCntY; y++) + { + for (int x = 0; x < sceneObjFile.FileHeader.SectionCntX; x++) + { + var list = sceneObjFile.objInfos[x, y]; + if (list is null) continue; + + foreach (var sceneObjInfo in list) + { + if (sceneObjInfo.GetTypeId() == 1) + continue; + + int id = sceneObjInfo.GetID(); + + CSceneObjInfo modeInfo = sceneObjSet.Get(id); + + Vector3 pos = new Vector3(sceneObjInfo.X / 100f, sceneObjInfo.HeightOff / 100f, + sceneObjInfo.Y / 100f * -1f); + float mapHeight = map.GetHeight(pos.x, (sceneObjInfo.Y / 100f)); + pos.y += mapHeight; + + //Quaternion rot = Quaternion.AngleAxis(sceneObjInfo.YawAngle, Vector3.up); + string modePath = "Assets/Resources/Model/Scene/" + + Path.GetFileNameWithoutExtension(modeInfo.szDataName) + ".lmo.obj"; + Object mode = AssetDatabase.LoadAssetAtPath(modePath); + if (mode) + { + GameObject goModel = (GameObject)GameObject.Instantiate(mode); + goModel.transform.position = pos; + goModel.transform.localScale = new Vector3(1, 1, -1); + Vector3 e = goModel.transform.eulerAngles; + goModel.transform.rotation = Quaternion.Euler(e.x, sceneObjInfo.YawAngle, e.z); + goModel.name = $"[{id}]{mode.name}"; + goModel.transform.SetParent(root.transform); + // Debug.Log(goModel); + } + else + { + Debug.LogError($"mode not found: {modePath}"); + } + } + } + } + } + + /// /// 清除场景中已生成的地图(父物体名称为 GENERATED_MAPS_PARENT) /// @@ -226,20 +285,69 @@ namespace MindPowerSdk.Editor // 遍历每个地图生成的子对象 foreach (Transform mapTransform in parent.transform) { - string prefabPath = "Assets/Prefabs/" + mapTransform.name + ".prefab"; - string directory = Path.GetDirectoryName(prefabPath); + if (mapTransform.name.Contains("SceneAssetsRoot")) + { + continue; + } + + string folder = EditorUtility.OpenFolderPanel("选择预制体路径", "", "") + $"/{mapTransform.name}/"; + string prefabPath = folder + mapTransform.name + ".prefab"; + + + string directory = Path.GetDirectoryName(prefabPath); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } + string materialDir = Path.GetDirectoryName(prefabPath) + "/Material"; + if (!Directory.Exists(materialDir)) + { + Directory.CreateDirectory(materialDir); + } + + string texturesDir = Path.GetDirectoryName(prefabPath) + "/Textures"; + if (!Directory.Exists(texturesDir)) + { + Directory.CreateDirectory(texturesDir); + } + + for (int i = 0; i < mapTransform.childCount; i++) + { + var child = mapTransform.GetChild(i); + var terrain = child.GetComponent(); + var terrainCollider = child.GetComponent(); + + + if (terrain != null) + { + materialDir = materialDir.Replace(@"\", "/"); + materialDir = materialDir.Replace(Application.dataPath, "Assets"); + materialDir = $"{materialDir}/{mapTransform.name}.mat"; + var terrainDataPath = directory.Replace(@"\", "/"); + terrainDataPath = terrainDataPath.Replace(Application.dataPath, "Assets"); + terrainDataPath = $"{terrainDataPath}/{mapTransform.name}.asset"; + if (File.Exists(materialDir)) + AssetDatabase.DeleteAsset(materialDir); + if (File.Exists(terrainDataPath)) + AssetDatabase.DeleteAsset(terrainDataPath); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + AssetDatabase.CreateAsset(terrain.materialTemplate, materialDir); + AssetDatabase.CreateAsset(terrainCollider.terrainData, terrainDataPath); + } + } + PrefabUtility.SaveAsPrefabAssetAndConnect(mapTransform.gameObject, prefabPath, InteractionMode.UserAction); + Debug.Log($"保存预制体:{prefabPath}"); } #else Debug.LogWarning("该功能仅在 Unity Editor 下可用"); #endif + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); } /// diff --git a/Assets/MindPowerSdk/EditorWindow/TerrainGenerator.cs b/Assets/MindPowerSdk/EditorWindow/TerrainGenerator.cs index 6a89afe..34e48eb 100644 --- a/Assets/MindPowerSdk/EditorWindow/TerrainGenerator.cs +++ b/Assets/MindPowerSdk/EditorWindow/TerrainGenerator.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using UnityEngine; using MindPowerSdk; @@ -14,9 +15,10 @@ public static class TerrainGenerator /// 生成的 Terrain 父节点 /// /// - public static void GenTerrain(MPMap map, int chunkSize, Material terrainMaterial, Transform parent, - string entryMapName, bool isSmoothing = true) + public static List GenTerrain(MPMap map, int chunkSize, Material terrainMaterial, Transform parent, + string entryMapName, bool isSmoothing = true) { + List textureList = new List(); // 计算全局高度范围(归一化用) (float globalMin, float globalMax) = ComputeGlobalHeightRange(map); @@ -55,7 +57,8 @@ public static class TerrainGenerator Debug.LogWarning($"{startX} {startY} {chunkSize}"); (Texture2D texNo, Texture2D maskNo) = map.GenTxtNoTexture((short)startX, (short)startY, chunkSize); - + textureList.Add(texNo); + textureList.Add(maskNo); // 设置每个 tile 在辅助 baked UV 贴图中希望的像素尺寸(建议不小于 4) int cellPixelSize = 7; @@ -80,7 +83,7 @@ public static class TerrainGenerator GameObject terrainGO = Terrain.CreateTerrainGameObject(terrainData); terrainGO.name = $"terrain_{i}_{j}"; terrainGO.transform.parent = terrainMap.transform; - terrainGO.transform.position = new Vector3(startX, globalMin, startY - chunkSize); + terrainGO.transform.position = new Vector3(startX, globalMin, startY - chunkSize + 1); Debug.Log($"terrainGO: {terrainGO.name} | pos: {terrainGO.transform.position}"); // 设置 Terrain 为自定义材质模式,并赋予生成的材质实例 Terrain terrainComponent = terrainGO.GetComponent(); @@ -88,6 +91,8 @@ public static class TerrainGenerator terrainComponent.materialTemplate = matInstance; } } + + return textureList; }