Files
AIGame/AIClient/AgentScripts/BuildBattlefieldAssets.cs

167 lines
7.2 KiB
C#

#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
/// <summary>
/// Imports the authored battlefield component FBX/XPbr files and creates one
/// reusable prefab per component. Ground is built separately so its collider
/// and read/write mesh settings cannot be confused with decoration assets.
/// </summary>
public static class BuildBattlefieldAssets
{
const string Root = "Assets/Bundles/Scenes/Prototype/Battlefield/A/Components";
const string GroundRoot = "Assets/Bundles/Scenes/Prototype/Battlefield/A/Ground";
const string GroundPrefab = "Assets/Bundles/Scenes/Prototype/Battlefield/GreenfieldGround.prefab";
const string XpbrShader = "Test/XPbr";
static readonly string[] Parts = { "tree", "rock", "bridge", "sign", "shrub" };
public static string BuildComponents()
{
AssetDatabase.Refresh();
var reports = new List<string>();
foreach (var type in Parts) reports.Add(BuildPart(type));
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
return string.Join(" | ", reports);
}
/// <summary>
/// Builds the independently authored ground asset once Hunyuan has produced
/// Ground/ground.fbx and its XPbr textures. The ground keeps a readable mesh
/// so the authored prefab can carry a non-convex MeshCollider.
/// </summary>
public static string BuildGround()
{
AssetDatabase.Refresh();
string fbxPath = GroundRoot + "/ground.fbx";
if (!File.Exists(fbxPath)) return "ground: missing fbx";
string basePath = GroundRoot + "/ground_base.png";
string mixPath = GroundRoot + "/ground_mix.png";
ConfigureTexture(basePath, true, true);
ConfigureTexture(mixPath, false, false);
var importer = AssetImporter.GetAtPath(fbxPath) as ModelImporter;
if (importer != null)
{
importer.globalScale = 1f;
importer.useFileScale = false;
importer.bakeAxisConversion = true;
importer.materialImportMode = ModelImporterMaterialImportMode.ImportViaMaterialDescription;
importer.meshCompression = ModelImporterMeshCompression.Medium;
importer.isReadable = true;
importer.addCollider = false;
importer.SaveAndReimport();
}
var mat = GetOrCreateMaterial(GroundRoot + "/ground.mat", "ground", basePath, mixPath);
var model = AssetDatabase.LoadAssetAtPath<GameObject>(fbxPath);
if (model == null) return "ground: fbx not loaded";
var root = new GameObject("GreenfieldGround");
try
{
var instance = (GameObject)PrefabUtility.InstantiatePrefab(model);
instance.name = "GroundMesh";
instance.transform.SetParent(root.transform, false);
PrefabUtility.UnpackPrefabInstance(instance, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
foreach (var renderer in instance.GetComponentsInChildren<Renderer>(true)) renderer.sharedMaterial = mat;
foreach (var filter in instance.GetComponentsInChildren<MeshFilter>(true))
{
if (filter.sharedMesh == null) continue;
var collider = filter.gameObject.GetComponent<MeshCollider>();
if (collider == null) collider = filter.gameObject.AddComponent<MeshCollider>();
collider.convex = false;
collider.sharedMesh = filter.sharedMesh;
}
PrefabUtility.SaveAsPrefabAsset(root, GroundPrefab);
}
finally { UnityEngine.Object.DestroyImmediate(root); }
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
return "ground: " + GroundPrefab;
}
public static string BuildAll()
{
var components = BuildComponents();
var ground = BuildGround();
return components + " | " + ground;
}
static string BuildPart(string type)
{
string dir = Root + "/" + type;
string fbxPath = dir + "/" + type + ".fbx";
string matPath = dir + "/" + type + ".mat";
string basePath = dir + "/" + type + "_base.png";
string mixPath = dir + "/" + type + "_mix.png";
string prefabPath = dir + "/" + type + ".prefab";
if (!File.Exists(fbxPath)) return type + ": missing fbx";
ConfigureTexture(basePath, true, true);
ConfigureTexture(mixPath, false, false);
var importer = AssetImporter.GetAtPath(fbxPath) as ModelImporter;
if (importer != null)
{
importer.globalScale = 1f;
importer.useFileScale = false;
importer.bakeAxisConversion = true;
importer.materialImportMode = ModelImporterMaterialImportMode.ImportViaMaterialDescription;
importer.meshCompression = ModelImporterMeshCompression.Medium;
importer.isReadable = false;
importer.addCollider = false;
importer.SaveAndReimport();
}
var mat = GetOrCreateMaterial(matPath, type, basePath, mixPath);
var model = AssetDatabase.LoadAssetAtPath<GameObject>(fbxPath);
if (model == null) return type + ": fbx not loaded";
var instance = (GameObject)PrefabUtility.InstantiatePrefab(model);
instance.name = type;
foreach (var renderer in instance.GetComponentsInChildren<Renderer>()) renderer.sharedMaterial = mat;
instance.transform.localPosition = Vector3.zero;
instance.transform.localRotation = Quaternion.identity;
instance.transform.localScale = Vector3.one;
PrefabUtility.SaveAsPrefabAsset(instance, prefabPath);
UnityEngine.Object.DestroyImmediate(instance);
return type + ": " + prefabPath;
}
static Material GetOrCreateMaterial(string matPath, string name, string basePath, string mixPath)
{
var baseMap = AssetDatabase.LoadAssetAtPath<Texture2D>(basePath);
var mixMap = AssetDatabase.LoadAssetAtPath<Texture2D>(mixPath);
var shader = Shader.Find(XpbrShader) ?? Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard");
var mat = AssetDatabase.LoadAssetAtPath<Material>(matPath);
if (mat == null)
{
mat = new Material(shader) { name = name };
AssetDatabase.CreateAsset(mat, matPath);
}
else mat.shader = shader;
if (mat.HasProperty("_MainTex")) mat.SetTexture("_MainTex", baseMap);
if (mat.HasProperty("_MixTex")) mat.SetTexture("_MixTex", mixMap);
if (mat.HasProperty("_BaseColor")) mat.SetColor("_BaseColor", Color.white);
if (mat.HasProperty("_Metallic")) mat.SetFloat("_Metallic", 1f);
if (mat.HasProperty("_Roughness")) mat.SetFloat("_Roughness", 1f);
if (mat.HasProperty("_AO")) mat.SetFloat("_AO", 1f);
EditorUtility.SetDirty(mat);
return mat;
}
static void ConfigureTexture(string path, bool srgb, bool alpha)
{
if (!File.Exists(path)) return;
var importer = AssetImporter.GetAtPath(path) as TextureImporter;
if (importer == null) return;
importer.textureType = TextureImporterType.Default;
importer.sRGBTexture = srgb;
importer.mipmapEnabled = true;
importer.alphaIsTransparency = alpha;
importer.SaveAndReimport();
}
}
#endif