167 lines
7.2 KiB
C#
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
|