2025-01-22 15:13:44 +08:00
|
|
|
|
using System.Collections.Generic;
|
2024-12-23 10:19:53 +08:00
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.Linq;
|
2026-01-16 19:26:53 +08:00
|
|
|
|
using Framework;
|
2025-07-14 14:45:42 +08:00
|
|
|
|
using Gameplay.Character;
|
2024-12-23 10:19:53 +08:00
|
|
|
|
using UnityEditor;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.UIElements;
|
|
|
|
|
|
|
2026-01-16 19:41:39 +08:00
|
|
|
|
namespace Art.temp.Editor.AnimationTools
|
2024-12-23 10:19:53 +08:00
|
|
|
|
{
|
2024-12-25 13:18:39 +08:00
|
|
|
|
public class AnimationTool : EditorWindow
|
|
|
|
|
|
{
|
2026-01-16 20:07:41 +08:00
|
|
|
|
[MenuItem("Test/Animation 工具/Animation")]
|
2025-01-22 15:13:44 +08:00
|
|
|
|
public static void ShowWindow()
|
|
|
|
|
|
{
|
|
|
|
|
|
GetWindow<AnimationTool>("Animation Tools");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-25 13:18:39 +08:00
|
|
|
|
public void CreateGUI()
|
|
|
|
|
|
{
|
2025-01-23 14:09:35 +08:00
|
|
|
|
var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Art/temp/Editor/CommonUSSFile.uss");
|
|
|
|
|
|
rootVisualElement.styleSheets.Add(styleSheet);
|
2025-02-08 15:56:44 +08:00
|
|
|
|
|
2024-12-25 13:18:39 +08:00
|
|
|
|
Box box1 = new();
|
|
|
|
|
|
box1.Add(new Label("Anim file tool"));
|
2025-01-15 13:56:35 +08:00
|
|
|
|
box1.Add(new Button() { name = "meta_btn", text = "重新生成 meta 文件并设置 avatar" });
|
2024-12-25 13:18:39 +08:00
|
|
|
|
box1.Add(new Button() { name = "renameClip_btn", text = "rename animationClip" });
|
2024-12-25 15:00:20 +08:00
|
|
|
|
box1.Add(new Button() { name = "copyAnim_btn", text = "提取 anim to compressedShow" });
|
2025-01-15 13:56:35 +08:00
|
|
|
|
box1.Add(new Button() { name = "copyTempAnim_btn", text = "提取 anim to compressed" });
|
|
|
|
|
|
box1.Add(new Button() { name = "find something", text = "Find Fire" });
|
2024-12-25 13:18:39 +08:00
|
|
|
|
rootVisualElement.Add(box1);
|
|
|
|
|
|
box1.Q<Button>("meta_btn").RegisterCallback<ClickEvent>(DeleteMeta);
|
|
|
|
|
|
box1.Q<Button>("renameClip_btn").RegisterCallback<ClickEvent>(RenameAnim);
|
|
|
|
|
|
box1.Q<Button>("copyAnim_btn").RegisterCallback<ClickEvent>(CopySelectedToCompressedShow);
|
2025-01-06 15:09:23 +08:00
|
|
|
|
box1.Q<Button>("copyTempAnim_btn").RegisterCallback<ClickEvent>(CopySelectedToTemp);
|
2025-01-15 13:56:35 +08:00
|
|
|
|
box1.Q<Button>("find something").RegisterCallback<ClickEvent>(FindSomething);
|
2024-12-25 13:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
Box box2 = new();
|
2025-01-22 15:13:44 +08:00
|
|
|
|
rootVisualElement.Add(box2);
|
2024-12-25 13:18:39 +08:00
|
|
|
|
box2.Add(new Label("other files tool"));
|
2026-01-16 19:26:53 +08:00
|
|
|
|
|
2025-01-22 15:13:44 +08:00
|
|
|
|
box2.Add(new Button() { name = "renameAssets_btn", text = "rename assets" });
|
2024-12-25 13:18:39 +08:00
|
|
|
|
box2.Q<Button>("renameAssets_btn").RegisterCallback<ClickEvent>(RenameAssets);
|
2026-01-16 19:26:53 +08:00
|
|
|
|
|
2026-01-13 13:35:32 +08:00
|
|
|
|
box2.Add(new Button() { name = "test", text = "test" });
|
2025-01-08 16:55:29 +08:00
|
|
|
|
box2.Q<Button>("test").RegisterCallback<ClickEvent>(Test);
|
2025-05-09 19:45:04 +08:00
|
|
|
|
|
2025-06-26 13:27:36 +08:00
|
|
|
|
box2.Add(new Button() { name = "MeshSimplify_btn", text = "character mesh simplify" });
|
|
|
|
|
|
box2.Q<Button>("MeshSimplify_btn").RegisterCallback<ClickEvent>(SimplifyCharacterMesh);
|
2025-06-05 16:07:48 +08:00
|
|
|
|
|
|
|
|
|
|
box2.Add(new Button() { name = "vehicleShader_btn", text = "vehicleShader" });
|
|
|
|
|
|
box2.Q<Button>("vehicleShader_btn").RegisterCallback<ClickEvent>(SetVehicleShader);
|
2025-07-14 14:45:42 +08:00
|
|
|
|
|
2025-08-01 18:31:43 +08:00
|
|
|
|
box2.Add(new Button() { name = "AddPoint_btn", text = "添加 hit Points" });
|
|
|
|
|
|
box2.Q<Button>("AddPoint_btn").RegisterCallback<ClickEvent>(AddHitPoints);
|
2026-01-06 17:30:34 +08:00
|
|
|
|
}
|
2025-08-01 18:31:43 +08:00
|
|
|
|
|
2026-01-06 17:30:34 +08:00
|
|
|
|
private static bool HasCombined(GameObject go)
|
|
|
|
|
|
{
|
|
|
|
|
|
Transform[] children = go.GetComponentsInChildren<Transform>();
|
|
|
|
|
|
bool hasCombined = children.Any(c => c.gameObject.name.StartsWith("Default_NLD"));
|
|
|
|
|
|
if (hasCombined) Debug.LogWarning("有合并mesh,需要重命名");
|
|
|
|
|
|
return hasCombined;
|
2025-07-14 14:45:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 17:30:34 +08:00
|
|
|
|
private static bool HasHitPoints(GameObject go)
|
|
|
|
|
|
{
|
|
|
|
|
|
Transform[] children = go.GetComponentsInChildren<Transform>();
|
|
|
|
|
|
bool hasHitPoints = children.Any(c => c.gameObject.name.StartsWith("hit"));
|
|
|
|
|
|
if (hasHitPoints) Debug.LogWarning("已有hit points");
|
|
|
|
|
|
return hasHitPoints;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void RenameDuplicateBones(GameObject go)
|
|
|
|
|
|
{
|
|
|
|
|
|
var groups = go.GetComponentsInChildren<Transform>()
|
|
|
|
|
|
.GroupBy(p => p.name)
|
|
|
|
|
|
.Where(g => g.Count() > 1)
|
|
|
|
|
|
.ToArray();
|
|
|
|
|
|
if (!groups.Any()) return;
|
|
|
|
|
|
foreach (var group in groups)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (int i = 0; i < group.Count(); i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
group.ElementAt(i).name = group.ElementAt(i).name + "_" + (i + 1);
|
|
|
|
|
|
}
|
2026-01-16 19:26:53 +08:00
|
|
|
|
|
2026-01-06 17:30:34 +08:00
|
|
|
|
Debug.Log("重命名重复骨骼:" + group.Key);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-23 15:53:11 +08:00
|
|
|
|
|
2025-08-01 18:31:43 +08:00
|
|
|
|
private static void AddHitPoints(ClickEvent evt)
|
2025-07-14 14:45:42 +08:00
|
|
|
|
{
|
|
|
|
|
|
GameObject[] gameObjects = Selection.gameObjects;
|
|
|
|
|
|
foreach (GameObject go in gameObjects)
|
|
|
|
|
|
{
|
2025-07-29 13:00:17 +08:00
|
|
|
|
GameObject instance = PrefabUtility.InstantiatePrefab(go) as GameObject;
|
|
|
|
|
|
if (instance == null) return;
|
2026-01-06 17:30:34 +08:00
|
|
|
|
bool hasCombined = HasCombined(instance);
|
|
|
|
|
|
bool hasHitPoints = HasHitPoints(instance);
|
|
|
|
|
|
RenameDuplicateBones(instance);
|
|
|
|
|
|
if (hasCombined || hasHitPoints) continue;
|
2025-07-29 13:00:17 +08:00
|
|
|
|
if (instance.name.EndsWith("_b")) continue;
|
2026-01-06 17:30:34 +08:00
|
|
|
|
|
|
|
|
|
|
// 添加 hit points
|
2025-07-14 14:45:42 +08:00
|
|
|
|
var pointEffect = instance.AddComponent<CmpCharacterEffectPoints>();
|
|
|
|
|
|
List<GameObject> points = new List<GameObject>();
|
|
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
|
|
{
|
2025-07-23 19:27:48 +08:00
|
|
|
|
var hit = new GameObject($"hit00{i + 1}");
|
2025-07-14 14:45:42 +08:00
|
|
|
|
hit.transform.SetParent(instance.transform);
|
|
|
|
|
|
points.Add(hit);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pointEffect.m_CriticalPoints = new[] { points[0].transform };
|
|
|
|
|
|
pointEffect.m_OtherPoints = new[] { points[1].transform, points[2].transform, points[3].transform };
|
|
|
|
|
|
}
|
2025-06-05 16:07:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-01 18:31:43 +08:00
|
|
|
|
|
2025-06-05 16:07:48 +08:00
|
|
|
|
private static void SetVehicleShader(ClickEvent evt)
|
|
|
|
|
|
{
|
|
|
|
|
|
string[] paths = { "Assets/Art/Character/Models/Battery", "Assets/Art/Character/Models/Vehicle" };
|
|
|
|
|
|
List<Object> objects = AnimHelper.FindAssetsByFolders<Object>(filter: "t:material", paths).ToList();
|
|
|
|
|
|
foreach (Object obj in objects)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (obj is Material mat)
|
|
|
|
|
|
{
|
2025-09-15 16:11:18 +08:00
|
|
|
|
if (mat.shader == Shader.Find("NLD_URP/NLD_Vehicle")) continue;
|
2025-06-05 16:07:48 +08:00
|
|
|
|
mat.shader = Shader.Find("NLD_URP/NLD_Vehicle");
|
|
|
|
|
|
// mat.SetFloat("_Factor", 0.2f);
|
|
|
|
|
|
Debug.Log(mat.name);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-26 13:27:36 +08:00
|
|
|
|
|
2025-06-05 16:07:48 +08:00
|
|
|
|
AssetDatabase.SaveAssets();
|
2025-05-09 19:45:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-26 13:27:36 +08:00
|
|
|
|
private static void SimplifyMesh(GameObject instance, float vertexAmount)
|
2025-05-09 19:45:04 +08:00
|
|
|
|
{
|
2025-05-14 16:16:21 +08:00
|
|
|
|
Debug.Log(instance.transform.childCount);
|
|
|
|
|
|
for (int i = 0; i < instance.transform.childCount; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
GameObject meshGameObject = instance.transform.GetChild(i).gameObject;
|
|
|
|
|
|
SkinnedMeshRenderer skin = meshGameObject.GetComponent<SkinnedMeshRenderer>();
|
|
|
|
|
|
|
|
|
|
|
|
if (skin == null) continue;
|
|
|
|
|
|
if (skin.sharedMesh == null) break;
|
|
|
|
|
|
string dir = Path.GetDirectoryName(AssetDatabase.GetAssetPath(skin.sharedMesh));
|
|
|
|
|
|
if (!Directory.Exists(dir)) break;
|
|
|
|
|
|
|
|
|
|
|
|
var simplify = meshGameObject.GetComponent<MeshSimplify>();
|
|
|
|
|
|
if (simplify == null) simplify = meshGameObject.AddComponent<MeshSimplify>();
|
2025-06-26 13:27:36 +08:00
|
|
|
|
simplify.m_fVertexAmount = vertexAmount;
|
2025-05-14 16:16:21 +08:00
|
|
|
|
simplify.m_bEnablePrefabUsage = true;
|
2025-06-26 13:27:36 +08:00
|
|
|
|
simplify.m_strAssetPath = Path.Combine(dir, skin.sharedMesh.name + "_simplyMesh.asset");
|
2025-05-14 16:16:21 +08:00
|
|
|
|
|
|
|
|
|
|
MeshSimplyTool.Create(simplify);
|
2025-06-26 13:27:36 +08:00
|
|
|
|
PrefabUtility.ApplyPrefabInstance(instance, InteractionMode.UserAction);
|
|
|
|
|
|
Debug.Log(Path.Combine(dir, skin.sharedMesh.name));
|
2025-05-14 16:16:21 +08:00
|
|
|
|
}
|
2025-05-09 19:45:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-26 13:27:36 +08:00
|
|
|
|
private static void SimplifyCharacterMesh(ClickEvent evt)
|
2025-05-09 19:45:04 +08:00
|
|
|
|
{
|
|
|
|
|
|
Object[] folders = Selection.objects;
|
|
|
|
|
|
string[] folderPaths = folders.Select(AssetDatabase.GetAssetPath).ToArray();
|
|
|
|
|
|
IEnumerable<Object> characters = AnimHelper.FindAssetsByFolders<GameObject>("character_", folderPaths);
|
|
|
|
|
|
|
|
|
|
|
|
int i = -1;
|
|
|
|
|
|
foreach (Object obj in characters)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (obj is not GameObject character) continue;
|
|
|
|
|
|
GameObject instance = (GameObject)PrefabUtility.InstantiatePrefab(character);
|
|
|
|
|
|
instance.transform.localPosition = new Vector3(i, 0, 0);
|
|
|
|
|
|
i--;
|
2025-05-14 16:16:21 +08:00
|
|
|
|
|
2025-06-26 13:27:36 +08:00
|
|
|
|
if (instance.name.StartsWith("character_A")) SimplifyMesh(instance, 0.6f);
|
|
|
|
|
|
if (instance.name.StartsWith("character_E")) SimplifyMesh(instance, 0.4f);
|
2025-05-09 19:45:04 +08:00
|
|
|
|
}
|
2024-12-25 13:18:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-01-22 15:13:44 +08:00
|
|
|
|
private static void RenameAnim(ClickEvent evt)
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2025-01-22 15:13:44 +08:00
|
|
|
|
var gos = Selection.gameObjects;
|
|
|
|
|
|
if (!gos.Any()) return;
|
2024-12-25 13:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
foreach (var go in gos)
|
|
|
|
|
|
{
|
|
|
|
|
|
string goPath = AssetDatabase.GetAssetPath(go);
|
|
|
|
|
|
ModelImporter importer = AssetImporter.GetAtPath(goPath) as ModelImporter;
|
2025-01-22 15:13:44 +08:00
|
|
|
|
if (!importer) continue;
|
2025-01-15 19:01:09 +08:00
|
|
|
|
importer.avatarSetup = ModelImporterAvatarSetup.CreateFromThisModel;
|
2024-12-25 13:18:39 +08:00
|
|
|
|
|
2025-01-22 15:13:44 +08:00
|
|
|
|
ModelImporterClipAnimation clip = importer.defaultClipAnimations[0];
|
2024-12-25 13:18:39 +08:00
|
|
|
|
clip.name = go.name;
|
2025-01-22 15:13:44 +08:00
|
|
|
|
importer.clipAnimations = new[] { clip };
|
2024-12-25 13:18:39 +08:00
|
|
|
|
importer.SaveAndReimport();
|
|
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2024-12-25 13:18:39 +08:00
|
|
|
|
AssetDatabase.Refresh();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-01-15 13:56:35 +08:00
|
|
|
|
// 删除 meta 文件, 设置 avatar
|
2025-01-22 15:13:44 +08:00
|
|
|
|
private static void DeleteMeta(ClickEvent evt)
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2025-01-22 15:13:44 +08:00
|
|
|
|
var objs = Selection.gameObjects;
|
2024-12-25 13:18:39 +08:00
|
|
|
|
if (objs.Length == 0)
|
|
|
|
|
|
{
|
2024-12-25 15:00:20 +08:00
|
|
|
|
Debug.LogWarning("请先选择至少一个Fbx文件");
|
2024-12-25 13:18:39 +08:00
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2024-12-25 13:18:39 +08:00
|
|
|
|
foreach (GameObject obj in objs)
|
|
|
|
|
|
{
|
|
|
|
|
|
string objPath = AssetDatabase.GetAssetPath(obj);
|
|
|
|
|
|
string metaPath = objPath + ".meta";
|
|
|
|
|
|
File.Delete(metaPath);
|
|
|
|
|
|
AssetDatabase.Refresh();
|
2025-01-15 13:56:35 +08:00
|
|
|
|
var modelImporter = AssetImporter.GetAtPath(objPath) as ModelImporter;
|
2025-01-22 15:13:44 +08:00
|
|
|
|
if (!modelImporter) continue;
|
2025-01-15 13:56:35 +08:00
|
|
|
|
modelImporter.avatarSetup = ModelImporterAvatarSetup.CreateFromThisModel;
|
|
|
|
|
|
modelImporter.SaveAndReimport();
|
2024-12-25 13:18:39 +08:00
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2024-12-25 13:18:39 +08:00
|
|
|
|
AssetDatabase.Refresh();
|
|
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
|
|
|
|
|
private static void FindSomething(ClickEvent evt)
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2025-03-12 14:05:02 +08:00
|
|
|
|
Object[] folders = Selection.objects;
|
2025-03-11 20:39:16 +08:00
|
|
|
|
string[] folderPaths = folders.Select(AssetDatabase.GetAssetPath).ToArray();
|
|
|
|
|
|
var objects = AnimHelper.FindAssetsByFolders<GameObject>("ani_", folderPaths);
|
2025-01-15 13:56:35 +08:00
|
|
|
|
foreach (var obj in objects)
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2025-01-15 13:56:35 +08:00
|
|
|
|
string fbxPath = AssetDatabase.GetAssetPath(obj);
|
|
|
|
|
|
var assets = AssetDatabase.LoadAllAssetRepresentationsAtPath(fbxPath);
|
|
|
|
|
|
var clips = assets.OfType<AnimationClip>();
|
2025-01-22 15:13:44 +08:00
|
|
|
|
var curves = clips.SelectMany(AnimationUtility.GetCurveBindings);
|
2025-01-15 13:56:35 +08:00
|
|
|
|
if (curves.Any(c => Path.GetFileName(c.path).StartsWith("Fire")))
|
|
|
|
|
|
Debug.LogWarning("f:" + obj.name);
|
2024-12-25 13:18:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-08 15:56:44 +08:00
|
|
|
|
private static void AnimOptimize(AnimationClip clip)
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2025-01-22 15:13:44 +08:00
|
|
|
|
var curveBindings = AnimationUtility.GetCurveBindings(clip);
|
2025-01-15 17:36:36 +08:00
|
|
|
|
for (int ii = 0; ii < curveBindings.Length; ++ii)
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2025-01-15 17:36:36 +08:00
|
|
|
|
AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, curveBindings[ii]);
|
2024-12-25 13:18:39 +08:00
|
|
|
|
|
2024-12-25 15:00:20 +08:00
|
|
|
|
// 删除移动帧(除了Bip001)和缩放帧
|
2025-01-15 17:36:36 +08:00
|
|
|
|
string propName = curveBindings[ii].propertyName.ToLower();
|
|
|
|
|
|
string nodeName = Path.GetFileName(curveBindings[ii].path);
|
|
|
|
|
|
/*if (propName.Contains("position") && nodeName.StartsWith("Bip001 "))
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2024-12-25 15:00:20 +08:00
|
|
|
|
curve = null; //有空格,排除了“Bip001”
|
2025-01-15 17:36:36 +08:00
|
|
|
|
}*/
|
2025-07-23 19:27:48 +08:00
|
|
|
|
if (propName.Contains("scale") && !nodeName.Contains("Grip_point01"))
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
|
|
|
|
|
curve = null;
|
|
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2025-01-15 13:56:35 +08:00
|
|
|
|
if (nodeName.StartsWith("Fire"))
|
|
|
|
|
|
{
|
|
|
|
|
|
curve = null;
|
|
|
|
|
|
}
|
2024-12-25 13:18:39 +08:00
|
|
|
|
|
2024-12-25 15:00:20 +08:00
|
|
|
|
// 压缩浮点数
|
2025-01-22 15:13:44 +08:00
|
|
|
|
if (curve is { keys: not null })
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2025-01-22 15:13:44 +08:00
|
|
|
|
var keyFrames = curve.keys;
|
2024-12-25 13:18:39 +08:00
|
|
|
|
for (int i = 0; i < keyFrames.Length; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Keyframe key = keyFrames[i];
|
|
|
|
|
|
key.value = float.Parse(key.value.ToString("f4"));
|
|
|
|
|
|
key.inTangent = float.Parse(key.inTangent.ToString("f4"));
|
|
|
|
|
|
key.outTangent = float.Parse(key.outTangent.ToString("f4"));
|
|
|
|
|
|
keyFrames[i] = key;
|
|
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2024-12-25 13:18:39 +08:00
|
|
|
|
curve.keys = keyFrames;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-01-15 13:56:35 +08:00
|
|
|
|
// curve 为 null, 则删除曲线
|
2025-01-15 17:36:36 +08:00
|
|
|
|
AnimationUtility.SetEditorCurve(clip, curveBindings[ii], curve);
|
2024-12-25 13:18:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-12-25 15:00:20 +08:00
|
|
|
|
// copy fbx 中一个或多个 anim 到 new path
|
2025-02-08 15:56:44 +08:00
|
|
|
|
private static string[] CopyAnim(GameObject fbx, string destFolder, bool toCompressed = false)
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
|
|
|
|
|
string fbxPath = AssetDatabase.GetAssetPath(fbx);
|
|
|
|
|
|
var assets = AssetDatabase.LoadAllAssetRepresentationsAtPath(fbxPath);
|
2025-01-22 15:13:44 +08:00
|
|
|
|
var animPaths = new List<string>();
|
|
|
|
|
|
foreach (Object asset in assets)
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2025-01-22 15:13:44 +08:00
|
|
|
|
if (asset is not AnimationClip clip) continue;
|
|
|
|
|
|
AnimOptimize(clip);
|
|
|
|
|
|
AnimationClip newClip = new();
|
|
|
|
|
|
EditorUtility.CopySerialized(clip, newClip);
|
|
|
|
|
|
string str = clip.name + ".anim";
|
|
|
|
|
|
string compressed = toCompressed ? "compressed_" + str : str;
|
|
|
|
|
|
string newPath = Path.Combine(destFolder, compressed);
|
|
|
|
|
|
AssetDatabase.CreateAsset(newClip, newPath);
|
|
|
|
|
|
Debug.Log(newPath);
|
|
|
|
|
|
animPaths.Add(newPath);
|
2024-12-25 13:18:39 +08:00
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2025-01-15 12:56:29 +08:00
|
|
|
|
return animPaths.ToArray();
|
2024-12-25 13:18:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void CopyToVictory(ClickEvent evt)
|
|
|
|
|
|
{
|
2025-01-22 15:13:44 +08:00
|
|
|
|
var objs = Selection.gameObjects;
|
2024-12-25 13:18:39 +08:00
|
|
|
|
|
2025-01-22 15:13:44 +08:00
|
|
|
|
const string folder = "Assets/Art/Animations/animVictory";
|
2024-12-25 13:18:39 +08:00
|
|
|
|
if (objs.Length == 0)
|
|
|
|
|
|
{
|
2024-12-25 15:00:20 +08:00
|
|
|
|
Debug.LogWarning("请先选择至少一个Fbx文件");
|
2024-12-25 13:18:39 +08:00
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2024-12-25 13:18:39 +08:00
|
|
|
|
foreach (GameObject obj in objs)
|
|
|
|
|
|
{
|
|
|
|
|
|
CopyAnim(obj, folder);
|
|
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2024-12-25 13:18:39 +08:00
|
|
|
|
AssetDatabase.Refresh();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void CopyToCompressedInShow(ClickEvent evt)
|
|
|
|
|
|
{
|
2025-01-22 15:13:44 +08:00
|
|
|
|
string[] guids = AssetDatabase.FindAssets("t:GameObject", new[]
|
|
|
|
|
|
{
|
|
|
|
|
|
"Assets/Art/Animations/Show/Battle",
|
|
|
|
|
|
"Assets/Art/Animations/Show/Ready",
|
|
|
|
|
|
"Assets/Art/Animations/Show/Story",
|
2024-12-25 13:18:39 +08:00
|
|
|
|
});
|
2025-01-22 15:13:44 +08:00
|
|
|
|
var paths = guids.Select(AssetDatabase.GUIDToAssetPath);
|
|
|
|
|
|
var objs = paths.Select(AssetDatabase.LoadAssetAtPath<GameObject>).ToArray();
|
2024-12-25 13:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-01-22 15:13:44 +08:00
|
|
|
|
const string folder = "Assets/Art/Animations/compressedShow";
|
2024-12-25 13:18:39 +08:00
|
|
|
|
|
|
|
|
|
|
foreach (GameObject obj in objs)
|
|
|
|
|
|
{
|
|
|
|
|
|
CopyAnim(obj, folder, true);
|
|
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2024-12-25 13:18:39 +08:00
|
|
|
|
AssetDatabase.Refresh();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-02-08 15:56:44 +08:00
|
|
|
|
private static void CopySelectedToCompressedShow(ClickEvent evt)
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2025-02-12 12:35:39 +08:00
|
|
|
|
// const string folder = "Assets/Art/Animations/compressedShow";
|
|
|
|
|
|
var objects = Selection.gameObjects;
|
2024-12-25 13:18:39 +08:00
|
|
|
|
|
2025-02-12 12:35:39 +08:00
|
|
|
|
const string tempFolder = "Assets/Art/temp/Animation";
|
|
|
|
|
|
const string destFilePath = "Assets/Art/Animations/compressedShow/{0}";
|
2024-12-25 13:18:39 +08:00
|
|
|
|
|
2025-02-12 12:35:39 +08:00
|
|
|
|
foreach (GameObject obj in objects)
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2025-02-12 12:35:39 +08:00
|
|
|
|
AnimHelper.PreSetModel(obj);
|
|
|
|
|
|
string[] fileNames = CopyAnim(obj, tempFolder, true);
|
|
|
|
|
|
foreach (string f in fileNames)
|
|
|
|
|
|
{
|
|
|
|
|
|
string destFile = string.Format(destFilePath, Path.GetFileName(f));
|
|
|
|
|
|
File.Copy(f, destFile, true);
|
|
|
|
|
|
Debug.Log(destFile);
|
|
|
|
|
|
}
|
2024-12-25 13:18:39 +08:00
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2024-12-25 13:18:39 +08:00
|
|
|
|
AssetDatabase.Refresh();
|
|
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2025-02-08 15:56:44 +08:00
|
|
|
|
private static void CopySelectedToTemp(ClickEvent evt)
|
2025-01-06 15:09:23 +08:00
|
|
|
|
{
|
2025-01-22 15:13:44 +08:00
|
|
|
|
var objects = Selection.gameObjects;
|
2025-01-06 15:09:23 +08:00
|
|
|
|
|
2025-01-22 15:13:44 +08:00
|
|
|
|
const string tempFolder = "Assets/Art/temp/Animation";
|
|
|
|
|
|
const string destFilePath = "Assets/Art/Animations/compressed/{0}";
|
2025-01-06 15:09:23 +08:00
|
|
|
|
|
2025-01-15 13:56:35 +08:00
|
|
|
|
foreach (GameObject obj in objects)
|
2025-01-15 12:56:29 +08:00
|
|
|
|
{
|
2025-02-08 15:56:44 +08:00
|
|
|
|
AnimHelper.PreSetModel(obj);
|
2025-01-15 13:56:35 +08:00
|
|
|
|
string[] fileNames = CopyAnim(obj, tempFolder, true);
|
|
|
|
|
|
foreach (string f in fileNames)
|
|
|
|
|
|
{
|
|
|
|
|
|
string destFile = string.Format(destFilePath, Path.GetFileName(f));
|
|
|
|
|
|
File.Copy(f, destFile, true);
|
|
|
|
|
|
Debug.Log(destFile);
|
|
|
|
|
|
}
|
2025-01-06 15:09:23 +08:00
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2025-01-06 15:09:23 +08:00
|
|
|
|
AssetDatabase.Refresh();
|
|
|
|
|
|
}
|
2024-12-25 13:18:39 +08:00
|
|
|
|
|
2025-01-22 15:13:44 +08:00
|
|
|
|
// rename assets
|
|
|
|
|
|
private static void RenameAssets(ClickEvent evt)
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2025-01-22 15:13:44 +08:00
|
|
|
|
// 选择的文件中的 GameObject
|
2025-09-23 15:53:11 +08:00
|
|
|
|
// Object[] folders = Selection.objects;
|
|
|
|
|
|
// string[] folderPath = folders.Select(AssetDatabase.GetAssetPath).ToArray();
|
|
|
|
|
|
// var objects = AnimHelper.FindAssetsByFolders<GameObject>("t:GameObject", folderPath);
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
|
|
|
|
|
// 选择的 gameObject
|
2025-09-23 15:53:11 +08:00
|
|
|
|
var objects = Selection.gameObjects.Where(g => g.name.EndsWith("_01"));
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
|
|
|
|
|
// 选择的 文件夹
|
|
|
|
|
|
// var objects = Selection.GetFiltered<Object>(SelectionMode.Assets);
|
|
|
|
|
|
|
2025-09-23 15:53:11 +08:00
|
|
|
|
foreach (GameObject obj in objects)
|
2024-12-25 13:18:39 +08:00
|
|
|
|
{
|
2025-09-23 15:53:11 +08:00
|
|
|
|
string name = obj.name.Split("_")[2];
|
|
|
|
|
|
string newName = "3" + name[1..];
|
2024-12-25 13:18:39 +08:00
|
|
|
|
string path = AssetDatabase.GetAssetPath(obj);
|
|
|
|
|
|
AssetDatabase.RenameAsset(path, newName);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AssetDatabase.Refresh();
|
|
|
|
|
|
}
|
2025-01-06 15:09:23 +08:00
|
|
|
|
|
2024-12-25 13:18:39 +08:00
|
|
|
|
public void MoveFiles(ClickEvent evt)
|
|
|
|
|
|
{
|
2025-01-22 15:13:44 +08:00
|
|
|
|
var objs = Selection.objects;
|
2024-12-25 13:18:39 +08:00
|
|
|
|
string folder = $"Assets/Art_Out/Manual/VictoryAnim";
|
|
|
|
|
|
|
|
|
|
|
|
foreach (Object obj in objs)
|
|
|
|
|
|
{
|
|
|
|
|
|
string oldPath = AssetDatabase.GetAssetPath(obj);
|
|
|
|
|
|
string fileName = Path.GetFileName(oldPath);
|
|
|
|
|
|
string newPath = Path.Combine(folder, fileName);
|
|
|
|
|
|
AssetDatabase.MoveAsset(oldPath, newPath);
|
|
|
|
|
|
Debug.Log(newPath);
|
|
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
|
2024-12-25 13:18:39 +08:00
|
|
|
|
AssetDatabase.Refresh();
|
|
|
|
|
|
}
|
2025-01-08 16:55:29 +08:00
|
|
|
|
|
2025-01-22 15:13:44 +08:00
|
|
|
|
private static void Test(ClickEvent evt)
|
2025-01-08 16:55:29 +08:00
|
|
|
|
{
|
2026-01-16 19:26:53 +08:00
|
|
|
|
var personDataList = ArtTableManager.instance.tables.PersonConfig.DataList;
|
|
|
|
|
|
foreach (var i in personDataList)
|
2025-12-17 16:26:57 +08:00
|
|
|
|
{
|
2026-01-16 19:26:53 +08:00
|
|
|
|
Debug.Log(i.Name);
|
2025-02-08 15:56:44 +08:00
|
|
|
|
}
|
2026-01-16 19:26:53 +08:00
|
|
|
|
|
|
|
|
|
|
Debug.Log(personDataList.Count);
|
2025-01-08 16:55:29 +08:00
|
|
|
|
}
|
2025-03-07 13:34:36 +08:00
|
|
|
|
|
2025-03-05 13:51:07 +08:00
|
|
|
|
private static void Combine()
|
|
|
|
|
|
{
|
|
|
|
|
|
GameObject obj = Selection.activeGameObject;
|
|
|
|
|
|
AnimHelper.PreSetAll(obj);
|
|
|
|
|
|
var go = Object.Instantiate(obj);
|
|
|
|
|
|
var nameId = obj.name.Split('_')[2];
|
|
|
|
|
|
var texNames = new[] { "_MainTex", "_MaskTex" };
|
|
|
|
|
|
var parentPath = $"Assets/Art/temp/Prefab/character_{nameId}";
|
|
|
|
|
|
if (!Directory.Exists(parentPath))
|
|
|
|
|
|
{
|
|
|
|
|
|
Directory.CreateDirectory(parentPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
AnimHelper.CombineSkinSaveAssets(go, texNames, parentPath);
|
|
|
|
|
|
// save prefab
|
|
|
|
|
|
string path = $"{parentPath}/character_{nameId}.prefab";
|
|
|
|
|
|
PrefabUtility.SaveAsPrefabAssetAndConnect(go, path, InteractionMode.AutomatedAction);
|
|
|
|
|
|
}
|
2024-12-25 13:18:39 +08:00
|
|
|
|
}
|
2025-01-22 15:13:44 +08:00
|
|
|
|
}
|