using UnityEngine; using UnityEditor; using System.IO; using System.Collections.Generic; using System.Linq; public class SetFishAnimationLoop : EditorWindow { // 需要设置Loop的动画名称 private string[] loopAnimations = new string[] { "Show01", "Swim01", "Idle01" }; // 手动输入鱼类名称(备用输入方式) private string manualInput = ""; // 拖入的 fishprocess_list.cs 文件引用 private TextAsset fishProcessListAsset; // 从 fishprocess_list.cs 中加载的鱼名 private string[] loadedFishList = null; [MenuItem("Tools/FishTools/Set Animation Loop")] static void Init() { SetFishAnimationLoop window = (SetFishAnimationLoop)EditorWindow.GetWindow(typeof(SetFishAnimationLoop)); window.titleContent = new GUIContent("Set Fish Loop Animations"); window.Show(); } void OnGUI() { GUILayout.Label("🎣 Fish Animation Loop Settings", EditorStyles.boldLabel); GUILayout.Space(10); GUILayout.Label("1️⃣ 手动输入鱼名(逗号或换行分隔):"); manualInput = EditorGUILayout.TextArea(manualInput, GUILayout.Height(60)); GUILayout.Space(15); GUILayout.Label("2️⃣ 或者拖入 fishprocess_list.cs 文件:"); fishProcessListAsset = (TextAsset)EditorGUILayout.ObjectField("fishprocess_list.cs", fishProcessListAsset, typeof(TextAsset), false); if (fishProcessListAsset != null) { if (GUILayout.Button("加载鱼类名单")) { LoadFishListFromAsset(fishProcessListAsset); } } if (loadedFishList != null && loadedFishList.Length > 0) { GUILayout.Label($"✅ 已加载 {loadedFishList.Length} 个鱼类"); } GUILayout.Space(20); if (GUILayout.Button("开始批量设置动画 Loop")) { ProcessFishAnimations(); } } private void LoadFishListFromAsset(TextAsset asset) { string content = asset.text; int start = content.IndexOf('{'); int end = content.IndexOf('}'); if (start == -1 || end == -1 || end <= start) { Debug.LogError("❌ 无法从文件中解析鱼类名单,请检查 fishprocess_list.cs 格式"); return; } string inside = content.Substring(start + 1, end - start - 1); loadedFishList = inside .Split(',') .Select(s => s.Trim().Trim('"').Trim('}', '{', ';')) .Where(s => !string.IsNullOrEmpty(s) && s.StartsWith("F_")) .ToArray(); Debug.Log($"✅ 成功从 {asset.name} 加载 {loadedFishList.Length} 个鱼类"); } private void ProcessFishAnimations() { List fishList = new List(); if (loadedFishList != null && loadedFishList.Length > 0) { fishList.AddRange(loadedFishList); } else if (!string.IsNullOrEmpty(manualInput)) { fishList.AddRange(manualInput .Split(new[] { ',', '\n', '\r' }, System.StringSplitOptions.RemoveEmptyEntries) .Select(f => f.Trim())); } else { Debug.LogError("❌ 未提供鱼类名单,请手动输入或加载文件。"); return; } string basePath = "Assets/AssetsPackage/art/fishsetting/mesh/"; int modifiedCount = 0; foreach (string fishName in fishList) { string cleanName = new string(fishName .Where(c => !Path.GetInvalidFileNameChars().Contains(c)) .ToArray()) .Trim() .Replace("\r", "") .Replace("\n", "") .Replace("\"", ""); string fishPath = Path.Combine(basePath, cleanName); if (!Directory.Exists(fishPath)) { Debug.LogWarning($"⚠️ 未找到路径: {fishPath}"); continue; } foreach (string anim in loopAnimations) { string fbxPath = Path.Combine(fishPath, $"{fishName}@{anim}.fbx"); if (!File.Exists(fbxPath)) { continue; } ModelImporter importer = AssetImporter.GetAtPath(fbxPath) as ModelImporter; if (importer != null) { var clips = importer.clipAnimations.Length > 0 ? importer.clipAnimations : importer.defaultClipAnimations; foreach (var clip in clips) { clip.loopTime = true; } importer.clipAnimations = clips; importer.SaveAndReimport(); modifiedCount++; Debug.Log($"✅ 设置循环动画: {fishName}@{anim}"); } } } Debug.Log($"🎯 完成设置,共修改 {modifiedCount} 个动画文件。"); } }