升级生成工具

This commit is contained in:
ZombieKitty 2025-05-09 17:39:24 +08:00
parent bee7af1732
commit c5877622c8
2 changed files with 125 additions and 12 deletions

View File

@ -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<Object>(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}");
}
}
}
}
}
/// <summary>
/// 清除场景中已生成的地图(父物体名称为 GENERATED_MAPS_PARENT
/// </summary>
@ -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<Terrain>();
var terrainCollider = child.GetComponent<TerrainCollider>();
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();
}
/// <summary>

View File

@ -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
/// <param name="parent">生成的 Terrain 父节点</param>
/// <param name="isSmoothing"></param>
/// <param name="entryMapName"></param>
public static void GenTerrain(MPMap map, int chunkSize, Material terrainMaterial, Transform parent,
string entryMapName, bool isSmoothing = true)
public static List<Texture> GenTerrain(MPMap map, int chunkSize, Material terrainMaterial, Transform parent,
string entryMapName, bool isSmoothing = true)
{
List<Texture> textureList = new List<Texture>();
// 计算全局高度范围(归一化用)
(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<Terrain>();
@ -88,6 +91,8 @@ public static class TerrainGenerator
terrainComponent.materialTemplate = matInstance;
}
}
return textureList;
}