using System.Collections.Generic; using System.IO; using cfg.VehicleCfg; using Framework; using Gameplay.Utils; using UnityEditor; using UnityEditor.Animations; using UnityEngine; namespace VehicleBuilder { /// /// 所有动作都可以没有 /// body使用的animator Assets/Art/Animations/animator/Vehicle/animator_vehicle.controller /// body需要的动作 Assets/Art/Animations/Vehicle/C00001/ani_C00001_D_dead.fbx /// dead /// idle /// move /// restart /// stop /// skill /// battery使用的animator Assets/Art/Animations/animator/Battery/animator_battery.controller /// battery需要的动作 Assets/Art/Animations/Battery/R00001/ani_R00001_attack01.fbx /// attack01 /// idle /// skill /// public class VehicleBuildData { public DataVehicle vehicleConfig; public bool isChecked; public string bodyName; public string batteryName; public string errorInfo; private string _prefabPath; private string[] _bodyAniNames = new string[] { "dead", "idle", "move", "restart", "stop", // "skill", }; public void Init() { var prefabPath = PathEx.GetVehicleSrcModelPath(vehicleConfig.PrefabPath); var prefab = AssetDatabase.LoadAssetAtPath(prefabPath); if (prefab == null) { errorInfo = $"载具预制体不存在:{prefabPath}"; return; } _prefabPath = prefabPath; var prefabName = prefab.name; var splits = prefabName.Split('_'); if (splits.Length != 3) { errorInfo = $"prefab命名错误:{prefabName}"; return; } bodyName = splits[1]; // 检查所有bodyanims for (var i = 0; i < _bodyAniNames.Length; ++i) { var bodyAnimName = _bodyAniNames[i]; var combinePath = $"Assets/Art/Animations/Vehicle/{bodyName}/ani_{bodyName}_D_{bodyAnimName}.fbx"; var loadAnim = AssetDatabase.LoadAssetAtPath(combinePath); if (loadAnim == null) { errorInfo = $"不存在需求动作: {combinePath}"; return; } } } public void DoBuild() { var savePath = string.Format(Constants.VEHICLE_OUTPUT_PATH, vehicleConfig.ID); var realPath = savePath.Replace("Assets", Application.dataPath); if (!Directory.Exists(realPath)) { Directory.CreateDirectory(realPath); } var loadPrefab = AssetDatabase.LoadAssetAtPath(_prefabPath); if (loadPrefab == null) { Debug.LogError($"找不到载具预制体:{_prefabPath}"); return; } loadPrefab = Object.Instantiate(loadPrefab); _HandlePrefab(loadPrefab, savePath); var savePrefabPath = $"{savePath}/vehicle_{vehicleConfig.ID}.prefab"; PrefabUtility.SaveAsPrefabAsset(loadPrefab, savePrefabPath); // 销毁prefab Object.DestroyImmediate(loadPrefab); Debug.Log($"生成载具预制体:{savePrefabPath}"); } private void _HandlePrefab(GameObject prefab, string savePath) { var allTrans = new List(); _DeepSearchTrans(prefab.transform, allTrans); var findBody = _SearchByName(allTrans, bodyName); if (findBody == null) { Debug.LogError($"找不到body:{bodyName}"); return; } // 删除炮台 var findBattery = _SearchByName(allTrans, "Battery_point01"); if (findBattery != null && findBattery.childCount > 0) { var child = findBattery.GetChild(0); if (child != null) { Object.DestroyImmediate(child.gameObject); } } // 处理body _HandleBody(savePath, findBody); EditorUtility.SetDirty(prefab); AssetDatabase.SaveAssets(); } private void _HandleBattery(string savePath, Transform findBattery) { var srcController = AssetDatabase.LoadAssetAtPath("Assets/Art/Animations/animator/Battery/animator_battery.controller"); if (srcController == null) { Debug.LogError($"找不到animator_battery.controller"); return; } // 创建一个overrideController var overrideController = new AnimatorOverrideController(); overrideController.runtimeAnimatorController = srcController; // 设置动作 var kvList = new List>(); var oldClips = overrideController.animationClips; for (int i = 0; i < oldClips.Length; i++) { var oldClip = oldClips[i]; var oldClipName = oldClip.name; // ani_R00001_attack01 var splits = oldClipName.Split('_'); var finalName = splits[^1]; var newClipPath = $"Assets/Art/Animations/Battery/{batteryName}/ani_{batteryName}_{finalName}.fbx"; var newClip = AssetDatabase.LoadAssetAtPath(newClipPath); if (newClip == null) { Debug.LogError($"找不到动作:{newClipPath}"); continue; } kvList.Add(new KeyValuePair(oldClip, newClip)); } overrideController.ApplyOverrides(kvList); // 保存controller var saveControllerPath = $"{savePath}/ov_battery_{vehicleConfig.ID}.controller"; AssetDatabase.CreateAsset(overrideController, saveControllerPath); AssetDatabase.Refresh(); overrideController = AssetDatabase.LoadAssetAtPath(saveControllerPath); // 设置battery的animator var batteryAnimator = findBattery.GetComponent(); if (batteryAnimator == null) { batteryAnimator = findBattery.gameObject.AddComponent(); } batteryAnimator.runtimeAnimatorController = overrideController; batteryAnimator.cullingMode = AnimatorCullingMode.AlwaysAnimate; } private void _HandleBody(string savePath, Transform findBody) { var srcController = AssetDatabase.LoadAssetAtPath("Assets/Art/Animations/animator/Vehicle/animator_vehicle.controller"); if (srcController == null) { Debug.LogError($"找不到animator_vehicle.controller"); return; } // 创建一个overrideController var overrideController = new AnimatorOverrideController(); overrideController.runtimeAnimatorController = srcController; // 设置动作 var kvList = new List>(); var oldClips = overrideController.animationClips; for (int i = 0; i < oldClips.Length; i++) { var oldClip = oldClips[i]; var oldClipName = oldClip.name; // ani_C00001_D_idle var splits = oldClipName.Split('_'); var finalName = splits[^1]; var newClipPath = $"Assets/Art/Animations/Vehicle/{bodyName}/ani_{bodyName}_D_{finalName}.fbx"; var newClip = AssetDatabase.LoadAssetAtPath(newClipPath); if (newClip == null) { Debug.LogError($"找不到动作:{newClipPath}"); continue; } kvList.Add(new KeyValuePair(oldClip, newClip)); } overrideController.ApplyOverrides(kvList); _CompressOverrideController(overrideController); // 保存controller var saveControllerPath = $"{savePath}/ov_vehicle_{vehicleConfig.ID}.controller"; AssetDatabase.CreateAsset(overrideController, saveControllerPath); AssetDatabase.Refresh(); overrideController = AssetDatabase.LoadAssetAtPath(saveControllerPath); // 设置body的animator var bodyAnimator = findBody.GetComponent(); if (bodyAnimator == null) { bodyAnimator = findBody.gameObject.AddComponent(); } bodyAnimator.runtimeAnimatorController = overrideController; bodyAnimator.cullingMode = AnimatorCullingMode.AlwaysAnimate; } private void _CompressOverrideController(AnimatorOverrideController overrideController) { var overrideClips = new List>(); overrideController.GetOverrides(overrideClips); var newClips = new List>(); foreach (var oldKV in overrideClips) { var srcClip = oldKV.Key; var dstClip = oldKV.Value; if (dstClip == null) { dstClip = srcClip; } var newClip = LTCompressor.AutoCompress(dstClip); newClips.Add(new KeyValuePair(srcClip, newClip)); } overrideController.ApplyOverrides(newClips); } private static Transform _SearchByName(List searchList, string name) { for (int i = 0; i < searchList.Count; i++) { var trans = searchList[i]; if (trans.name == name) { return trans; } } return null; } private static void _DeepSearchTrans(Transform searchTrans, List result) { result.Add(searchTrans); for (int i = 0; i < searchTrans.childCount; i++) { var child = searchTrans.GetChild(i); _DeepSearchTrans(child, result); } } } }