Files
ft/Client/Assets/Editor/FishiTool/ArtActorPrefabModifyWindow.cs
2026-06-29 21:18:33 +08:00

1319 lines
55 KiB
C#

using System.Collections.Generic;
using System.Data;
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using cfg;
using SimpleJSON;
using UnityEditor.Animations;
using Path = System.IO.Path;
using RootMotion.FinalIK;
public class ArtActorPrefabModifyWindow : EditorWindow
{
public static string assetSrcFolderPath = "Assets/AssetsPackage/art/fishsetting/mesh";
public static string assetDstFolderPath = "Assets/ABPackage/pkgDownloads/Fish"; //"Assets/AssetsPackage/Prefabs/Fishing/Fish";
public static string assetRodDstFolderPath = "Assets/ABPackage/pkgDownloads/Rod";
public static string fishMaterialFolderPath = "Assets/AssetsPackage/art/fishsetting/materials/";
public static string reelMaterialFolderPath = "Assets/AssetsPackage/art/fishingrod/reel/materials/";
public static string rodMaterialFolderPath = "Assets/AssetsPackage/art/fishingrod/rod/materials/";
public static string baseFishOverrideControllerPath = "Assets/AssetsPackage/Animation/Fishing/Fish/";
public static string baseRodOverrideControllerPath = "Assets/AssetsPackage/Animation/Fishing/Rod/";
public static UnityEditor.Animations.AnimatorController animatorController;
public static string animatorOverrideControllerPath = "Assets/AssetsPackage/art/fishsetting/animations/";
public static UnityEditor.Animations.AnimatorController animatorRodController;
public static string animatorRodControllerPath = "Assets/AssetsPackage/art/fishingrod/rod/animations/";
private Object jsonFile;
private string folderPath = "Assets/ABPackage/pkgDownloads/Fish";
private int startLine;
private int endLine;
static string crossbowPrefabPath = "Assets/ABPackage/pkgDownloads/Aquarium/AquariumCommon/Crossbow/";
public static string baseCrossbowOverrideControllerPath = "Assets/AssetsPackage/art/fishingcrossbow/animations/";
static UnityEditor.Animations.AnimatorController animatorCrossbowController;
public static string animatorCrossbowControllerPath = "Assets/AssetsPackage/art/fishingcrossbow/animations/";
[MenuItem("Window/自动化构建工具", false, 1)]
public static void ShowWindow()
{
EditorWindow thisWindow = EditorWindow.GetWindow(typeof(ArtActorPrefabModifyWindow));
thisWindow.titleContent = new GUIContent("创建Prefab");
thisWindow.position = new Rect(Screen.width / 2, Screen.height / 2, 600, 800);
}
private void OnEnable()
{
// 设置默认的json文件
string defaultJsonPath = "Assets/ABPackage/pkgData/Export/tbfishdata.json";
jsonFile = AssetDatabase.LoadAssetAtPath(defaultJsonPath, typeof(TextAsset));
}
void OnGUI()
{
//分一个组
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("批量创建鱼的Prefab", EditorStyles.boldLabel);
EditorGUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("选择源文件夹");
assetSrcFolderPath = EditorGUILayout.TextField(assetSrcFolderPath);
if (GUILayout.Button("选择"))
{
assetSrcFolderPath = EditorUtility.OpenFolderPanel("选择文件夹", assetSrcFolderPath, "");
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("选择保存文件夹");
assetDstFolderPath = EditorGUILayout.TextField(assetDstFolderPath);
if (GUILayout.Button("选择"))
{
assetDstFolderPath = EditorUtility.OpenFolderPanel("选择文件夹", assetDstFolderPath, "");
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
animatorController = (AnimatorController)EditorGUILayout.ObjectField("animatorController", animatorController, typeof(AnimatorController), false);
EditorGUILayout.EndHorizontal();
if (GUILayout.Button("开始创建") && assetSrcFolderPath != null && assetDstFolderPath != null)
{
Seperate(GetAbsolutePath(assetSrcFolderPath));
}
EditorGUILayout.Space(10);
//分组结束
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical("box");
EditorGUILayout.EndVertical();
EditorGUILayout.BeginVertical("box");
EditorGUILayout.LabelField("CheckFishFilesInFolder", EditorStyles.boldLabel);
// 创建可以拖拽Excel表的字段
jsonFile = EditorGUILayout.ObjectField("Json File tbfishdata", jsonFile, typeof(TextAsset), false);
// 获取拖进去的文件夹路径
if (Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform)
{
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
if (Event.current.type == EventType.DragPerform)
{
DragAndDrop.AcceptDrag();
foreach (string path in DragAndDrop.paths)
{
if (Directory.Exists(path))
{
folderPath = path;
break;
}
}
}
}
// 显示文件夹路径
EditorGUILayout.LabelField("Folder Path: " + folderPath);
// 输入起始行和结束行
startLine = EditorGUILayout.IntField("Start Line", startLine);
endLine = EditorGUILayout.IntField("End Line", endLine);
// 检查文件夹中是否存在指定文件
if (GUILayout.Button("Check Files"))
{
CheckFiles();
}
//分组结束
EditorGUILayout.EndVertical();
}
void CheckFiles()
{
// 读取json文件
string jsonString = (jsonFile as TextAsset).ToString();
var jsonData = new TbFishData(JSON.Parse(jsonString));
// 获取指定区间的数据
List<string> fileNames = new List<string>();
if (startLine < 1)
{
startLine = 1;
}
if (endLine > jsonData.DataList.Count)
{
endLine = jsonData.DataList.Count;
}
for (int i = startLine - 1; i < endLine; i++)
{
fileNames.Add(jsonData.DataList[i].Fbx);
}
// 检查文件夹中是否存在指定文件
List<string> missingFiles = new List<string>();
foreach (string fileName in fileNames)
{
string filePath = System.IO.Path.Combine(folderPath, fileName + ".prefab");
if (!File.Exists(filePath))
{
missingFiles.Add(fileName);
}
}
// 打印缺失文件名
if (missingFiles.Count > 0)
{
Debug.Log("The following files are missing:");
foreach (string missingFile in missingFiles)
{
Debug.Log(missingFile);
}
}
else
{
Debug.Log("All files are present.");
}
}
private static void Seperate(string folderPath)
{
//*.prefab或*.Fbx
var folders = Directory.GetDirectories(folderPath, "F_*", SearchOption.TopDirectoryOnly);
foreach (var folder in folders)
{
var files = Directory.GetFiles(folder, "*.*")
.Where(file => file.EndsWith(".prefab") || file.EndsWith(".fbx") || file.EndsWith(".FBX")).ToArray();
string srcPath = GetRelativePath(files[0]);
GameObject prefab = AssetDatabase.LoadAssetAtPath(srcPath, typeof(GameObject)) as GameObject;
if (prefab == null)
continue;
string fileName = Path.GetFileNameWithoutExtension(srcPath);
string directory = Path.GetDirectoryName(srcPath);
string newPath = Path.Combine(directory, fileName);
AssetsFish(prefab, newPath);
}
}
public static string GetRelativePath(string path)
{
string srcPath = path.Replace("\\", "/");
var retPath = Regex.Replace(srcPath, @"^(.*?/)Assets/", "Assets/");
return retPath;
}
public static string GetAbsolutePath(string path)
{
string srcPath = path.Replace("\\", "/");
//替换第一个Assets之前的路径
var retPath = Regex.Replace(srcPath, @"^(.*?/)Assets", Application.dataPath);
return retPath;
}
#region
[MenuItem("Assets/FISH_Tools/遍历文件夹下的鱼prefab查找节点")]
static void MenuAssetsFinFishNodes()
{
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
var files = Directory.GetFiles(path, "*.prefab");
foreach (var file in files)
{
string srcPath = GetRelativePath(file);
GameObject prefab = AssetDatabase.LoadAssetAtPath(srcPath, typeof(GameObject)) as GameObject;
if (prefab == null)
continue;
Fish fish = prefab.GetComponent<Fish>();
if (fish == null)
{
Debug.LogError($"{prefab.name}不是可钓的鱼");
continue;
}
FindFishNode(fish, prefab.transform);
LogNullNode(prefab.name, fish);
EditorUtility.SetDirty(prefab);
}
AssetDatabase.SaveAssets();
}
[MenuItem("Assets/FISH_Tools/遍历文件夹下的鱼prefab查找节点", true)]
private static bool MenuAssetsFinFishNodesValidation()
{
// 设置什么情况下消失/显现(the menu item will be disabled otherwise).
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
return AssetDatabase.IsValidFolder(path);
}
[MenuItem("Assets/FISH_Tools/遍历文件夹下的鱼prefab检查偏移")]
static void MenuAssetsCheckFishPos()
{
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
var files = Directory.GetFiles(path, "*.prefab");
foreach (var file in files)
{
string srcPath = GetRelativePath(file);
GameObject prefab = AssetDatabase.LoadAssetAtPath(srcPath, typeof(GameObject)) as GameObject;
if (prefab == null)
continue;
Fish fish = prefab.GetComponent<Fish>();
if (fish == null)
{
Debug.LogError($"{prefab.name}不是可钓的鱼");
continue;
}
//FindFishNode(fish, prefab.transform);
//LogNullNode(prefab.name, fish);
//EditorUtility.SetDirty(prefab);
if (fish.animator != null)
{
if (fish.animator.transform.localPosition != Vector3.zero)
{
Debug.LogError($"{prefab.name}的animator有偏移{fish.animator.transform.localPosition}");
}
}
else
{
Debug.LogError($"{prefab.name}缺少animator节点");
}
}
AssetDatabase.SaveAssets();
}
[MenuItem("Assets/FISH_Tools/遍历文件夹下的鱼prefab检查偏移", true)]
private static bool MenuAssetsCheckFishPosValidation()
{
// 设置什么情况下消失/显现(the menu item will be disabled otherwise).
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
return AssetDatabase.IsValidFolder(path);
}
[MenuItem("Assets/FISH_Tools/遍历文件夹下的鱼prefab设置动画")]
static void MenuAssetsFinFishAni()
{
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
var files = Directory.GetFiles(path, "*.prefab");
foreach (var file in files)
{
string srcPath = GetRelativePath(file);
GameObject prefab = AssetDatabase.LoadAssetAtPath(srcPath, typeof(GameObject)) as GameObject;
if (prefab == null)
continue;
Fish fish = prefab.GetComponent<Fish>();
if (fish == null)
{
Debug.LogError($"{prefab.name}不是可钓的鱼");
continue;
}
srcPath = $"{GetRelativePath(assetSrcFolderPath)}/{prefab.name}/{prefab.name}";
SetFishAni(fish, srcPath);
}
AssetDatabase.SaveAssets();
}
[MenuItem("Assets/FISH_Tools/遍历文件夹下的鱼prefab设置动画", true)]
private static bool MenuAssetsFinFishAniValidation()
{
// 设置什么情况下消失/显现(the menu item will be disabled otherwise).
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
return AssetDatabase.IsValidFolder(path);
}
[MenuItem("Assets/FISH_Tools/遍历文件夹下的鱼prefab检查节点")]
static void MenuAssetsCheckFishNodes()
{
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
var files = Directory.GetFiles(path, "*.prefab");
foreach (var file in files)
{
string srcPath = GetRelativePath(file);
GameObject prefab = AssetDatabase.LoadAssetAtPath(srcPath, typeof(GameObject)) as GameObject;
if (prefab == null)
continue;
Fish fish = prefab.GetComponent<Fish>();
if (fish == null)
{
Debug.LogError($"{prefab.name}不是可钓的鱼");
continue;
}
LogNullNode(prefab.name, fish);
}
}
[MenuItem("Assets/FISH_Tools/遍历文件夹下的鱼prefab检查节点", true)]
private static bool MenuAssetsCheckFishNodesValidation()
{
// 设置什么情况下消失/显现(the menu item will be disabled otherwise).
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
return AssetDatabase.IsValidFolder(path);
}
[MenuItem("Assets/FISH_Tools/遍历文件夹下的鱼prefab检查Layer")]
static void MenuAssetsCheckFishLayer()
{
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
var files = Directory.GetFiles(path, "*.prefab");
foreach (var file in files)
{
string srcPath = GetRelativePath(file);
GameObject prefab = AssetDatabase.LoadAssetAtPath(srcPath, typeof(GameObject)) as GameObject;
if (prefab == null)
continue;
LogRendererLayer(prefab);
}
}
[MenuItem("Assets/FISH_Tools/遍历文件夹下的鱼prefab检查Layer", true)]
private static bool MenuAssetsCheckFishLayerValidation()
{
// 设置什么情况下消失/显现(the menu item will be disabled otherwise).
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
return AssetDatabase.IsValidFolder(path);
}
[MenuItem("Assets/FISH_Tools/文件夹下创建鱼Prefab", true)]
private static bool MenuAssetsFishFValidation()
{
// 设置什么情况下消失/显现(the menu item will be disabled otherwise).
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
return Directory.Exists(path);
}
[MenuItem("Assets/FISH_Tools/文件夹下创建鱼Prefab")]
static void MenuAssetsFishF()
{
if (Selection.activeObject == null)
{
Debug.Log("Assets choose null");
}
else
{
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
Seperate(path);
}
}
[MenuItem("Assets/FISH_Tools/创建鱼Prefab", true)]
private static bool MenuAssetsFishValidation()
{
// 设置什么情况下消失/显现(the menu item will be disabled otherwise).
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
return path.EndsWith(".fbx") || path.EndsWith(".FBX") || path.EndsWith(".prefab");
}
[MenuItem("Assets/FISH_Tools/创建鱼Prefab")]
static void MenuAssetsFish()
{
if (Selection.activeObject == null)
{
Debug.Log("Assets choose null");
}
else
{
Debug.Log("Assets name = " + Selection.activeObject.name);
GameObject prefab = Selection.activeObject as GameObject;
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
string fileName = Path.GetFileNameWithoutExtension(path);
string directory = Path.GetDirectoryName(path);
string newPath = Path.Combine(directory, fileName);
AssetsFish(prefab, newPath);
}
}
static void AssetsFish(GameObject prefab, string srcPath)
{
string dstPath = GetRelativePath(assetDstFolderPath);
GameObject dstObj = new GameObject(prefab.name, typeof(Fish), typeof(BoxCollider));
GameObject srcObj = Instantiate(prefab, dstObj.transform, false);
srcObj.transform.localPosition = Vector3.zero;
srcObj.transform.localEulerAngles = Vector3.up * 180;
srcObj.transform.localScale = Vector3.one;
srcObj.name = prefab.name;
ConvertToPrefabInstanceSettings settings = new ConvertToPrefabInstanceSettings();
PrefabUtility.ConvertToPrefabInstance(srcObj, prefab, settings, InteractionMode.AutomatedAction);
Fish fish = dstObj.GetComponent<Fish>();
Renderer skinnedMeshRenderer = srcObj.GetComponentInChildren<Renderer>();
//Add Material
var fishMaterial = AssetDatabase.LoadAssetAtPath($"{fishMaterialFolderPath}/{prefab.name}.mat", typeof(Material)) as Material;
if (skinnedMeshRenderer != null && fishMaterial != null)
{
skinnedMeshRenderer.material = fishMaterial;
}
else if (skinnedMeshRenderer == null)
{
Debug.LogError($"{prefab.name} :没有 Renderer");
}
else
{
Debug.LogError($"{prefab.name} :没有名为 {prefab.name} 的 fishMaterial");
}
FindFishNode(fish, srcObj.transform);
fish.animator = srcObj.AddComponent<Animator>();
SetFishAni(fish, srcPath);
//dstObj下的layer都变成fish
SetLayerRecursively(dstObj, LayerMask.NameToLayer("fish"));
//设置脏数据
LogNullNode(srcObj.name, fish);
EditorUtility.SetDirty(dstObj);
PrefabUtility.SaveAsPrefabAsset(dstObj, dstPath + "/" + prefab.name + ".prefab");
Debug.Log($"创建{prefab.name}成功");
DestroyImmediate(dstObj);
}
static void SetFishAni(Fish fish, string srcPath)
{
//创建新的 Animator Override Controller并设置到fish.animator上
AnimatorOverrideController animatorOverrideController = new AnimatorOverrideController();
if (animatorController == null)
{
animatorController = AssetDatabase.LoadAssetAtPath<AnimatorController>(baseFishOverrideControllerPath + "fishGeneralAnimator.controller");
}
animatorOverrideController.runtimeAnimatorController = animatorController;
if (!string.IsNullOrEmpty(srcPath))
{
srcPath = srcPath.Replace(@"\", "/");
AnimationClip clip;
List<KeyValuePair<AnimationClip, AnimationClip>> overrides = new List<KeyValuePair<AnimationClip, AnimationClip>>();
animatorOverrideController.GetOverrides(overrides);
string clipName;
bool isHasClip = false;
bool isHasDash01 = false;
bool isHasShow01 = false;
foreach (var pair in overrides)
{
clipName = pair.Key.name;
string clipPath = $"{srcPath}@{clipName}.fbx";
clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(clipPath);
if (clip)
{
if (clipName.Equals("Dash01"))
{
isHasDash01 = true;
}
if (clipName.Equals("Show01"))
{
isHasShow01 = true;
}
isHasClip = true;
if (clipName.Equals("Idle01") || clipName.Equals("Swim01") || clipName.Equals("Show01"))
{
AnimationClipSettings clipSettings = AnimationUtility.GetAnimationClipSettings(clip);
clipSettings.loopTime = true;
AnimationUtility.SetAnimationClipSettings(clip, clipSettings);
//修改FBX的Animation的ModelImporter的循环属性
ModelImporter importer = AssetImporter.GetAtPath(clipPath) as ModelImporter;
ModelImporterClipAnimation modelImporterClipAnimation = importer.defaultClipAnimations[0];
modelImporterClipAnimation.loopTime = true;
importer.clipAnimations = new[] { modelImporterClipAnimation };
AssetDatabase.ImportAsset(clipPath);
}
animatorOverrideController[clipName] = clip;
}
}
if (!isHasClip)
{
return;
}
if (!isHasDash01)
{
animatorOverrideController["Dash01"] = animatorOverrideController["Swim01"];
}
if (!isHasShow01)
{
animatorOverrideController["Show01"] = animatorOverrideController["Swim01"];
}
//保存animatorOverrideController到指定文件夹
AssetDatabase.CreateAsset(animatorOverrideController, animatorOverrideControllerPath + fish.name + ".overrideController");
AssetDatabase.SaveAssets();
fish.animator.runtimeAnimatorController = animatorOverrideController;
}
}
static void FindFishNode(Fish fish, Transform root)
{
if (root.name.Equals("Mouth"))
{
fish.mouthPos = root;
}
else if (root.name.Equals("Head"))
{
fish.Head = root;
}
else if (root.name.Equals("Left_Eye"))
{
fish.LeftEye = root;
}
else if (root.name.Equals("Right_Eye"))
{
fish.RightEye = root;
}
else if (root.name.Equals("Fin"))
{
fish.Fin = root;
}
else if (root.name.Equals("Tail"))
{
fish.Tail = root;
}
else if (root.name.Equals("Neck"))
{
fish.Neck = root;
}
else if (root.name.Equals("Root"))
{
fish.Root = root;
}
foreach (Transform child in root)
{
FindFishNode(fish, child);
}
}
static void LogNullNode(string objName, Fish fish)
{
string nullNode = $"{objName}: 缺少";
bool isLog = false;
if (fish.mouthPos == null)
{
nullNode += "-|-Mouth";
isLog = true;
}
if (fish.Head == null)
{
nullNode += "-|-Head"; isLog = true;
}
if (fish.LeftEye == null)
{
nullNode += "-|-Left_Eye"; isLog = true;
}
if (fish.RightEye == null)
{
nullNode += "-|-Right_Eye"; isLog = true;
}
if (fish.Fin == null)
{
nullNode += "-|-Fin"; isLog = true;
}
if (fish.Tail == null)
{
nullNode += "-|-Tail"; isLog = true;
}
if (fish.Neck == null)
{
nullNode += "-|-Neck"; isLog = true;
}
if (isLog)
{
Debug.LogError(nullNode);
}
}
static void LogRendererLayer(GameObject obj)
{
Renderer skinnedMeshRenderer = obj.GetComponentInChildren<Renderer>();
if (skinnedMeshRenderer == null)
{
Debug.LogError($"{obj.name}: 缺少SkinnedMeshRenderer");
}
else
{
//skinnedMeshRenderer.renderingLayerMask 是包含 //fish = 1 << 0 //rod = 1 << 1 = 2
if ((skinnedMeshRenderer.renderingLayerMask & 1) == 0)
{
Debug.LogError($"{obj.name}: skinnedMeshRenderer.renderingLayerMask 不包含 fish");
}
if (skinnedMeshRenderer.gameObject.layer != LayerMask.NameToLayer("fish"))
{
Debug.LogError($"{obj.name}: skinnedMeshRenderer.Layer 不是 fish");
}
}
}
static void SetLayerRecursively(GameObject obj, int layer)
{
obj.layer = layer;
foreach (Transform child in obj.transform)
{
SetLayerRecursively(child.gameObject, layer);
}
}
[MenuItem("Assets/FISH_Tools/Fish_改名")]
static void GenerateFish()
{
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
string[] filePaths = Directory.GetFiles(path, "*.prefab", SearchOption.AllDirectories);
foreach (string filePath in filePaths)
{
string fileName = System.IO.Path.GetFileNameWithoutExtension(filePath);
if (!fileName.StartsWith("Fish_"))
{
string[] nameParts = Regex.Split(fileName, @"\s+");
nameParts = nameParts.Where(part => !part.Equals("Variant")).ToArray();
nameParts = nameParts.Select(part => char.ToUpper(part[0]) + part.Substring(1)).ToArray();
string fishName = "Fish_" + string.Join("", nameParts);
// string newFilePath = Path.Combine(path, fishName + Path.GetExtension(filePath));
AssetDatabase.RenameAsset(filePath, fishName);
// AssetDatabase.ImportAsset(newFilePath);
Debug.Log(fishName);
}
}
}
[MenuItem("Assets/FISH_Tools/Fish_改名", true)]
static bool GenerateFishValidation()
{
//选中的是文件夹
return AssetDatabase.IsValidFolder(AssetDatabase.GetAssetPath(Selection.activeObject));
}
#endregion
#region
[MenuItem("Assets/Rod_Tools/遍历文件夹下的杆prefab查找动画")]
static void MenuAssetsFinRodAnimator()
{
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
var files = Directory.GetFiles(path, "*.prefab");
foreach (var file in files)
{
string srcPath = GetRelativePath(file);
GameObject prefab = AssetDatabase.LoadAssetAtPath(srcPath, typeof(GameObject)) as GameObject;
if (prefab == null)
continue;
string prefabName = prefab.name;
var animator = prefab.transform.Find(prefabName).GetComponent<Animator>();
List<KeyValuePair<AnimationClip, AnimationClip>> overrides = new List<KeyValuePair<AnimationClip, AnimationClip>>();
var animatorOverrideController = animator.runtimeAnimatorController as AnimatorOverrideController;
animatorOverrideController.GetOverrides(overrides);
string clipName;
AnimationClip clip;
foreach (var pair in overrides)
{
clipName = pair.Key.name;
string clipPath = $"Assets/AssetsPackage/art/fishingrod/rod/mesh/{prefabName}/{prefabName}@{clipName}.fbx";
ModelImporter modelImporter = AssetImporter.GetAtPath(clipPath) as ModelImporter;
if (modelImporter != null)
{
clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(clipPath);
if (clipName.Equals("Idle01")
|| clipName.Contains("Drawing")
|| clipName.Contains("Reeling")
|| clipName.Contains("Waiting01")
|| clipName.Contains("Waiting02")
|| clipName.Contains("MaxCombo01")
|| clipName.Contains("Show01")
&& !clipName.Equals("Drawing00"))
{
AnimationClipSettings clipSettings = AnimationUtility.GetAnimationClipSettings(clip);
clipSettings.loopTime = true;
AnimationUtility.SetAnimationClipSettings(clip, clipSettings);
//修改FBX的Animation的ModelImporter的循环属性
ModelImporterClipAnimation modelImporterClipAnimation = modelImporter.defaultClipAnimations[0];
modelImporterClipAnimation.loopTime = true;
modelImporter.clipAnimations = new[] { modelImporterClipAnimation };
AssetDatabase.ImportAsset(clipPath);
}
animatorOverrideController[clipName] = clip;
}
}
}
AssetDatabase.SaveAssets();
}
[MenuItem("Assets/Rod_Tools/遍历文件夹下的杆prefab查找动画", true)]
private static bool MenuAssetsFinRodAnimatorValidation()
{
// 设置什么情况下消失/显现(the menu item will be disabled otherwise).
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
return AssetDatabase.IsValidFolder(path);
}
[MenuItem("Assets/Rod_Tools/创建鱼竿Prefab")]
static void MenuAssetsRod()
{
if (Selection.activeObject == null)
{
Debug.Log("Assets choose null");
}
else
{
Debug.Log("Assets name = " + Selection.activeObject.name);
GameObject prefab = Selection.activeObject as GameObject;
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
string fileName = Path.GetFileNameWithoutExtension(path);
string directory = Path.GetDirectoryName(path);
string newPath = Path.Combine(directory, fileName);
if (fileName.StartsWith("Rod_"))
{
AssetsRod(prefab, newPath);
}
}
}
[MenuItem("Assets/Rod_Tools/创建鱼竿Prefab", true)]
private static bool MenuAssetssRodValidation()
{
// 设置什么情况下消失/显现(the menu item will be disabled otherwise).
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
string fileName = Path.GetFileNameWithoutExtension(path);
return fileName.StartsWith("Rod_") && (path.EndsWith(".FBX") || path.EndsWith(".fbx") || path.EndsWith(".prefab"));
}
static void AssetsRod(GameObject prefab, string srcPath = "")
{
string dstPath = GetRelativePath(assetRodDstFolderPath);
GameObject dstObj = new GameObject(prefab.name, typeof(Rod), typeof(CCDIK));
GameObject srcObj = Instantiate(prefab, dstObj.transform, false);
ConvertToPrefabInstanceSettings settings = new ConvertToPrefabInstanceSettings();
PrefabUtility.ConvertToPrefabInstance(srcObj, prefab, settings, InteractionMode.AutomatedAction);
Rod rod = dstObj.GetComponent<Rod>();
rod.cCDIK = dstObj.GetComponent<CCDIK>();
rod.rod = srcObj;
rod.LineList = new List<Transform>();
FindRodNode(rod, srcObj.transform);
//rod.LineList.Reverse();
rod.LineList = rod.LineList.OrderByDescending(t => t.name).ToList();
//========================================Line===========================================//
var FishingLinePrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/AssetsPackage/Prefabs/Fishing/Component/FishingLine.prefab");
var fishingLine = Instantiate(FishingLinePrefab, dstObj.transform, false);
PrefabUtility.ConvertToPrefabInstance(fishingLine, FishingLinePrefab, settings, InteractionMode.AutomatedAction);
rod.fishingLineRenderer = fishingLine.GetComponent<LineRenderer>();
//========================================================================================//
SetRodAndReelMaterial(srcObj.transform);
var animator = srcObj.AddComponent<Animator>();
//创建新的 Animator Override Controller
if (animatorRodController == null)
{
animatorRodController = AssetDatabase.LoadAssetAtPath<AnimatorController>(baseRodOverrideControllerPath + "RodAnimatorController.controller");
}
AnimatorOverrideController animatorOverrideController = new AnimatorOverrideController();
animatorOverrideController.runtimeAnimatorController = animatorRodController;
if (!string.IsNullOrEmpty(srcPath))
{
string clipName;
srcPath = srcPath.Replace(@"\", "/");
AnimationClip clip;
List<KeyValuePair<AnimationClip, AnimationClip>> overrides = new List<KeyValuePair<AnimationClip, AnimationClip>>();
animatorOverrideController.GetOverrides(overrides);
foreach (var pair in overrides)
{
clipName = pair.Key.name;
string clipPath = $"{srcPath}@{clipName}.fbx";
ModelImporter modelImporter = AssetImporter.GetAtPath(clipPath) as ModelImporter;
if (modelImporter != null)
{
modelImporter.resampleCurves = false;
modelImporter.animationCompression = ModelImporterAnimationCompression.Optimal;
clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(clipPath);
if (clipName.Equals("Idle01")
|| clipName.Contains("Drawing")
|| clipName.Contains("Reeling")
|| clipName.Contains("Waiting01")
|| clipName.Contains("Waiting02")
|| clipName.Contains("MaxCombo01")
|| clipName.Contains("Show01")
&& !clipName.Equals("Drawing00"))
{
AnimationClipSettings clipSettings = AnimationUtility.GetAnimationClipSettings(clip);
clipSettings.loopTime = true;
AnimationUtility.SetAnimationClipSettings(clip, clipSettings);
//修改FBX的Animation的ModelImporter的循环属性
ModelImporter importer = AssetImporter.GetAtPath(clipPath) as ModelImporter;
ModelImporterClipAnimation modelImporterClipAnimation = importer.defaultClipAnimations[0];
modelImporterClipAnimation.loopTime = true;
importer.clipAnimations = new[] { modelImporterClipAnimation };
AssetDatabase.ImportAsset(clipPath);
}
animatorOverrideController[clipName] = clip;
}
}
}
//保存animatorOverrideController到指定文件夹
AssetDatabase.CreateAsset(animatorOverrideController, animatorRodControllerPath + prefab.name + ".overrideController");
animator.runtimeAnimatorController = animatorOverrideController;
AssetDatabase.SaveAssets();
//设置脏数据
EditorUtility.SetDirty(dstObj);
PrefabUtility.SaveAsPrefabAsset(dstObj, dstPath + "/" + prefab.name + ".prefab");
Debug.Log($"创建{prefab.name}成功");
DestroyImmediate(dstObj);
}
static void FindRodNode(Rod rod, Transform root)
{
if (root.name.Equals("Rod_Joint"))
{
rod.Rod_Joint = root;
}
else if (root.name.Equals("Bait"))
{
rod.Bait = root;
}
else if (root.name.Equals("TopLine"))
{
rod.TopLine = root; //TopLine;
}
else if (root.name.Equals("EndLine"))
{
rod.EndLine = root; //EndLine;
}
else if (Regex.IsMatch(root.name, @"^Line\d+$"))
{
rod.LineList.Add(root);
}
else if (root.name.Equals("LineHole"))
{
rod.LineHole = root;
}
else if (root.name.Equals("Bip001 L Hand"))
{
//========================================HandleLeft===========================================//
// var HandleLeft = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/ABPackage/pkgDownloads/Hand/HandleLeft.prefab");
// var handleLeft = Instantiate(HandleLeft, root.transform, false);
// ConvertToPrefabInstanceSettings settings = new ConvertToPrefabInstanceSettings();
// PrefabUtility.ConvertToPrefabInstance(handleLeft, HandleLeft, settings, InteractionMode.AutomatedAction);
rod.LeftHandTargets = root;
//========================================================================================//
}
else if (root.name.Equals("Bip001 R Hand"))
{
// //========================================HandleRight===========================================//
// var HandleLeft = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/ABPackage/pkgDownloads/Hand/HandleRight.prefab");
// var handleLeft = Instantiate(HandleLeft, root.transform, false);
// ConvertToPrefabInstanceSettings settings = new ConvertToPrefabInstanceSettings();
// PrefabUtility.ConvertToPrefabInstance(handleLeft, HandleLeft, settings, InteractionMode.AutomatedAction);
rod.RightHandTargets = root;
//========================================================================================//
}
else if (root.name.Equals("Bip001 Spine"))
{
rod.BodyTargets = root;
//========================================================================================//
}
foreach (Transform child in root)
{
FindRodNode(rod, child);
}
}
static Transform FindChildTransform(Transform root, string childName, bool isRoot)
{
if (root.name.Replace(" ", "").Equals(childName) && !isRoot)
{
return root;
}
for (int i = 0; i < root.childCount; i++)
{
var result = FindChildTransform(root.GetChild(i), childName, false);
if (result != null)
return result;
}
return null;
}
static Transform FindChildTransformStartWithName(Transform root, string pattern, bool isRoot)
{
if (root.name.StartsWith(pattern) && !isRoot)
return root;
for (int i = 0; i < root.childCount; i++)
{
var result = FindChildTransformStartWithName(root.GetChild(i), pattern, false);
if (result != null)
return result;
}
return null;
}
static void SetRodAndReelMaterial(Transform root)
{
// 检查root是否为空
if (root == null)
{
Debug.LogError("SetRodAndReelMaterial: root parameter is null!");
return;
}
// 检查root名称格式是否正确
if (!root.name.Contains("_"))
{
Debug.LogError($"SetRodAndReelMaterial: root name '{root.name}' does not contain '_' character!");
return;
}
var name = root.name.Split('_')[1];
var rodName = $"Rod_{name}";
var reelName = $"Reel_{name}";
var reellineName = $"Reelline_{name}";
var fishingLineName = "Fishing_line";
var rawRod = FindChildTransform(root, rodName, true);
var rawReel = FindChildTransform(root, reelName, true);
var rawReelline = FindChildTransform(root, reellineName, true);
var rawLine = FindChildTransformStartWithName(root, fishingLineName, true);
// 分别检查每个节点是否找到,并单独报错
if (rawRod == null)
{
Debug.LogError($"SetRodAndReelMaterial: Cannot find rod node '{rodName}' in root '{root.name}'");
}
if (rawReel == null)
{
Debug.LogError($"SetRodAndReelMaterial: Cannot find reel node '{reelName}' in root '{root.name}'");
}
if (rawReelline == null)
{
Debug.LogError($"SetRodAndReelMaterial: Cannot find reelline node '{reellineName}' in root '{root.name}'");
}
if (rawLine == null)
{
Debug.LogWarning($"SetRodAndReelMaterial: Cannot find fishing line node '{fishingLineName}' in root '{root.name}' (this is optional)");
}
// 如果关键节点缺失,直接返回
if (rawRod == null || rawReel == null || rawReelline == null)
{
Debug.LogError($"SetRodAndReelMaterial: Critical nodes missing in root '{root.name}'. Please check the prefab structure.");
return;
}
var rodRender = rawRod.GetComponent<SkinnedMeshRenderer>();
var reelRender = rawReel.GetComponent<SkinnedMeshRenderer>();
var reellineRender = rawReelline.GetComponent<SkinnedMeshRenderer>();
// 检查Renderer组件
if (rodRender == null)
{
Debug.LogError($"SetRodAndReelMaterial: SkinnedMeshRenderer component not found on rod node '{rodName}'");
return;
}
if (reelRender == null)
{
Debug.LogError($"SetRodAndReelMaterial: SkinnedMeshRenderer component not found on reel node '{reelName}'");
return;
}
if (reellineRender == null)
{
Debug.LogError($"SetRodAndReelMaterial: SkinnedMeshRenderer component not found on reelline node '{reellineName}'");
return;
}
//Add Material
var RodMaterial = AssetDatabase.LoadAssetAtPath($"{rodMaterialFolderPath}/{rodName}.mat", typeof(Material)) as Material;
var ReelMaterial = AssetDatabase.LoadAssetAtPath($"{reelMaterialFolderPath}/{reelName}.mat", typeof(Material)) as Material;
var ReellineMaterial = AssetDatabase.LoadAssetAtPath($"{reelMaterialFolderPath}/{reellineName}.mat", typeof(Material)) as Material;
// 检查材质是否加载成功
if (RodMaterial == null)
{
Debug.LogError($"SetRodAndReelMaterial: Failed to load rod material from path '{rodMaterialFolderPath}/{rodName}.mat'");
}
if (ReelMaterial == null)
{
Debug.LogError($"SetRodAndReelMaterial: Failed to load reel material from path '{reelMaterialFolderPath}/{reelName}.mat'");
}
if (ReellineMaterial == null)
{
Debug.LogError($"SetRodAndReelMaterial: Failed to load reelline material from path '{reelMaterialFolderPath}/{reellineName}.mat'");
}
Debug.Log($"SetRodAndReelMaterial: Loaded materials - Rod: {RodMaterial}, Reel: {ReelMaterial}, Reelline: {ReellineMaterial}");
// 应用材质
rodRender.material = RodMaterial;
reelRender.material = ReelMaterial;
reellineRender.material = ReellineMaterial;
//Change MeshRender
//layer
int layerIndex = LayerMask.NameToLayer("rod");
rodRender.renderingLayerMask = (uint)(1 << 1);
reelRender.renderingLayerMask = (uint)(1 << 1);
reellineRender.renderingLayerMask = (uint)(1 << 1);
if (rawLine != null)
{
var fishLineRender = rawLine.GetComponent<SkinnedMeshRenderer>();
if (fishLineRender != null)
{
fishLineRender.renderingLayerMask = (uint)(1 << 1);
fishLineRender.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
rawLine.gameObject.layer = layerIndex;
}
else
{
Debug.LogWarning($"SetRodAndReelMaterial: SkinnedMeshRenderer component not found on fishing line node '{fishingLineName}'");
}
}
//Cast Shadows
rodRender.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
reelRender.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
reellineRender.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
//Change Layer
rawReel.gameObject.layer = layerIndex;
rawRod.gameObject.layer = layerIndex;
rawReelline.gameObject.layer = layerIndex;
Debug.Log($"SetRodAndReelMaterial: Successfully processed rod, reel, and reelline for '{root.name}'");
}
#endregion
#region Crossbow相关工具
[MenuItem("Assets/Crossbow_Tools/创建弩Prefab")]
private static void MenuAssetsCrossbow()
{
if (Selection.activeObject == null)
{
Debug.Log("Assets choose null");
}
else
{
Debug.Log("Assets name = " + Selection.activeObject.name);
GameObject prefab = Selection.activeObject as GameObject;
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
string fileName = Path.GetFileNameWithoutExtension(path);
string directory = Path.GetDirectoryName(path);
string newPath = Path.Combine(directory, fileName);
if (fileName.Contains("prop_crossbow_"))
{
AssetsCrossbow(prefab, newPath);
}
}
}
[MenuItem("Assets/Crossbow_Tools/创建弩Prefab", true)]
private static bool MenuAssetsCrossbowValidation()
{
// 设置什么情况下消失/显现(the menu item will be disabled otherwise).
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
string fileName = Path.GetFileNameWithoutExtension(path);
return fileName.Contains("prop_crossbow_") && (path.EndsWith(".FBX") || path.EndsWith(".fbx"));
}
static void FindCrossbowNode(Crossbow crossbow, Transform root)
{
if (root.name.Equals("Root"))
{
crossbow.root = root.gameObject;
}
else if (root.name.Equals("crosshair_P"))
{
crossbow.crosshair_P = root;
}
else if (root.name.Equals("TopLine"))
{
crossbow.TopLine = root; //TopLine;
}
else if (root.name.Equals("EndLine"))
{
crossbow.EndLine = root; //EndLine;
}
else if (Regex.IsMatch(root.name, @"^Line\d+$"))
{
crossbow.LineList.Add(root);
}
else if (root.name.Equals("Bip001 L Hand"))
{
crossbow.LeftHandTargets = root;
}
else if (root.name.Equals("Bip001 R Hand"))
{
crossbow.RightHandTargets = root;
}
//LeftHandTargets
foreach (Transform child in root)
{
FindCrossbowNode(crossbow, child);
}
}
static void AssetsCrossbow(GameObject prefab, string srcPath = "")
{
string dstPath = GetRelativePath(crossbowPrefabPath);
GameObject dstObj = new GameObject(prefab.name, typeof(Crossbow));
GameObject srcObj = Instantiate(prefab, dstObj.transform, false);
ConvertToPrefabInstanceSettings settings = new ConvertToPrefabInstanceSettings();
PrefabUtility.ConvertToPrefabInstance(srcObj, prefab, settings, InteractionMode.AutomatedAction);
Crossbow crossbow = dstObj.GetComponent<Crossbow>();
crossbow.animator = srcObj.AddComponent<Animator>();
crossbow.LineList = new List<Transform>();
FindCrossbowNode(crossbow, srcObj.transform);
crossbow.LineList.Reverse();
//========================================Line===========================================//
var FishingLinePrefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/AssetsPackage/Prefabs/Fishing/Component/FishingLine.prefab");
var fishingLine = Instantiate(FishingLinePrefab, dstObj.transform, false);
PrefabUtility.ConvertToPrefabInstance(fishingLine, FishingLinePrefab, settings, InteractionMode.AutomatedAction);
crossbow.fishingLineRenderer = fishingLine.GetComponent<LineRenderer>();
//========================================================================================//
//========================================C_Crosshair===========================================//
var C_CrosshairPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(crossbowPrefabPath + "C_Crosshair.prefab");
var crosshair = Instantiate(C_CrosshairPrefab, crossbow.crosshair_P, false);
PrefabUtility.ConvertToPrefabInstance(crosshair, C_CrosshairPrefab, settings, InteractionMode.AutomatedAction);
crossbow.icon_nml = crossbow.crosshair_P.Find("C_Crosshair/icon_nml").gameObject;
crossbow.icon_notarget = crossbow.crosshair_P.Find("C_Crosshair/icon_notarget").gameObject;
//========================================================================================//
//创建新的 Animator Override Controller
SetCrossbowAni(crossbow, srcPath);
//dstObj下的layer都变成rod
SetLayerRecursively(dstObj, LayerMask.NameToLayer("rod"));
//设置脏数据
EditorUtility.SetDirty(dstObj);
PrefabUtility.SaveAsPrefabAsset(dstObj, dstPath + "/" + prefab.name + ".prefab");
Debug.Log($"创建{prefab.name}成功");
DestroyImmediate(dstObj);
}
static void SetCrossbowAni(Crossbow crossbow, string srcPath)
{
//创建新的 Animator Override Controller并设置到fish.animator上
SetCrossbow(crossbow.animator, crossbow.name, srcPath, "CrossbowAnimatorController.controller");
}
[MenuItem("Assets/Crossbow_Tools/创建弩箭Prefab")]
private static void MenuAssetsCrossbowArrow()
{
if (Selection.activeObject == null)
{
Debug.Log("Assets choose null");
}
else
{
Debug.Log("Assets name = " + Selection.activeObject.name);
GameObject prefab = Selection.activeObject as GameObject;
string path = AssetDatabase.GetAssetPath(Selection.activeObject);
string fileName = Path.GetFileNameWithoutExtension(path);
string directory = Path.GetDirectoryName(path);
string newPath = Path.Combine(directory, fileName);
if (fileName.Contains("prop_crossbowarrow_"))
{
AssetsCrossbowArrow(prefab, newPath);
}
}
}
[MenuItem("Assets/Crossbow_Tools/创建弩箭Prefab", true)]
private static bool MenuAssetsCrossbowArrowValidation()
{
// 设置什么情况下消失/显现(the menu item will be disabled otherwise).
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
string fileName = Path.GetFileNameWithoutExtension(path);
return fileName.Contains("prop_crossbowarrow_") && (path.EndsWith(".FBX") || path.EndsWith(".fbx"));
}
static void FindCrossbowArrowNode(CrossbowArrow crossbowArrow, Transform root)
{
if (root.name.Equals("TopLine"))
{
crossbowArrow.TopLine = root; //TopLine;
}
else if (root.name.Equals("EndLine"))
{
crossbowArrow.EndLine = root; //EndLine;
}
else if (Regex.IsMatch(root.name, @"^Line\d+$"))
{
crossbowArrow.LineList.Add(root);
}
foreach (Transform child in root)
{
FindCrossbowArrowNode(crossbowArrow, child);
}
}
static void AssetsCrossbowArrow(GameObject prefab, string srcPath = "")
{
string dstPath = GetRelativePath(crossbowPrefabPath);
GameObject dstObj = new GameObject(prefab.name, typeof(CrossbowArrow));
GameObject srcObj = Instantiate(prefab, dstObj.transform, false);
ConvertToPrefabInstanceSettings settings = new ConvertToPrefabInstanceSettings();
PrefabUtility.ConvertToPrefabInstance(srcObj, prefab, settings, InteractionMode.AutomatedAction);
CrossbowArrow crossbowArrow = dstObj.GetComponent<CrossbowArrow>();
crossbowArrow.animator = srcObj.AddComponent<Animator>();
crossbowArrow.crossbow = srcObj;
crossbowArrow.LineList = new List<Transform>();
FindCrossbowArrowNode(crossbowArrow, srcObj.transform);
crossbowArrow.LineList.Reverse();
//创建新的 Animator Override Controller
SetCrossbowArrowAni(crossbowArrow, srcPath);
//dstObj下的layer都变成rod
SetLayerRecursively(dstObj, LayerMask.NameToLayer("rod"));
//设置脏数据
EditorUtility.SetDirty(dstObj);
PrefabUtility.SaveAsPrefabAsset(dstObj, dstPath + "/" + prefab.name + ".prefab");
Debug.Log($"创建{prefab.name}成功");
DestroyImmediate(dstObj);
}
static void SetCrossbowArrowAni(CrossbowArrow crossbowArrow, string srcPath)
{
//创建新的 Animator Override Controller并设置到fish.animator上
SetCrossbow(crossbowArrow.animator, crossbowArrow.name, srcPath, "CrossbowArrowAnimatorController.controller");
}
static void SetCrossbow(Animator animator, string nameStr, string srcPath, string animatorController)
{
//创建新的 Animator Override Controller并设置到fish.animator上
AnimatorOverrideController animatorOverrideController = new AnimatorOverrideController();
if (animatorCrossbowController == null)
{
animatorCrossbowController = AssetDatabase.LoadAssetAtPath<AnimatorController>(baseCrossbowOverrideControllerPath + animatorController);
}
animatorOverrideController.runtimeAnimatorController = animatorCrossbowController;
if (!string.IsNullOrEmpty(srcPath))
{
srcPath = srcPath.Replace(@"\", "/");
AnimationClip clip;
List<KeyValuePair<AnimationClip, AnimationClip>> overrides = new List<KeyValuePair<AnimationClip, AnimationClip>>();
animatorOverrideController.GetOverrides(overrides);
string clipName;
bool isHasClip = false;
foreach (var pair in overrides)
{
clipName = pair.Key.name;
string clipPath = $"{srcPath}@{clipName}.fbx";
clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(clipPath);
if (clip)
{
isHasClip = true;
ModelImporter importer = AssetImporter.GetAtPath(clipPath) as ModelImporter;
importer.animationCompression = ModelImporterAnimationCompression.Optimal;
importer.resampleCurves = false;
if (clipName.Equals("Idle01"))
{
AnimationClipSettings clipSettings = AnimationUtility.GetAnimationClipSettings(clip);
clipSettings.loopTime = true;
AnimationUtility.SetAnimationClipSettings(clip, clipSettings);
//修改FBX的Animation的ModelImporter的循环属性
ModelImporterClipAnimation modelImporterClipAnimation = importer.defaultClipAnimations[0];
modelImporterClipAnimation.loopTime = true;
importer.clipAnimations = new[] { modelImporterClipAnimation };
}
AssetDatabase.ImportAsset(clipPath);
animatorOverrideController[clipName] = clip;
}
}
if (!isHasClip)
{
return;
}
//保存animatorOverrideController到指定文件夹
AssetDatabase.CreateAsset(animatorOverrideController, animatorCrossbowControllerPath + nameStr + ".overrideController");
AssetDatabase.SaveAssets();
animator.runtimeAnimatorController = animatorOverrideController;
}
}
#endregion
}