Files
Fishing2/Assets/Scripts/Editor/Fix/RF4FixPrefab.cs
2025-05-10 12:49:47 +08:00

808 lines
25 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using RootMotion.FinalIK;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace NBF
{
public class RF4FixPrefab : Editor
{
#region
[MenuItem("Assets/Fix/修复圈", false, 1)]
private static void FixRings()
{
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixRing(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼圈失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixRing(GameObject prefab)
{
var rings = prefab.GetComponent<RodRingAsset>();
if (rings == null)
{
rings = prefab.AddComponent<RodRingAsset>();
}
List<Transform> list = new List<Transform>();
// 遍历所有直接子对象
for (int i = 0; i < prefab.transform.childCount; i++)
{
Transform child = prefab.transform.GetChild(i);
list.Add(child);
}
// rings.rings = list.ToArray();
List<Transform> points = new List<Transform>();
foreach (var tran in list)
{
for (int i = 0; i < tran.childCount; i++)
{
Transform c = tran.GetChild(i);
if (c.name.Contains("Collider"))
{
points.Add(c);
break;
}
}
}
// rings.points = points.ToArray();
List<RodRingNode> saveList = new List<RodRingNode>();
foreach (var node in list)
{
RodRingNode ringNode = new RodRingNode
{
ring = node
};
foreach (var point in points)
{
if (point.parent != node) continue;
ringNode.point = point;
var rig = point.GetComponent<Rigidbody>();
if (rig == null)
{
rig = point.gameObject.AddComponent<Rigidbody>();
}
if (rig != null)
{
rig.useGravity = false;
rig.isKinematic = true;
rig.mass = 1;
}
break;
}
saveList.Add(ringNode);
}
rings.rings = saveList.ToArray();
EditorUtility.SetDirty(prefab);
}
#endregion
#region 竿
//joint_root
[MenuItem("Assets/Fix/修复鱼竿", false, 2)]
private static void FixRods()
{
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixRod(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼竿失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixRod(GameObject prefab)
{
RemoveMissingScriptsFrom(prefab);
var lineRenderer = prefab.GetComponent<LineRenderer>();
if (lineRenderer == null)
{
lineRenderer = prefab.AddComponent<LineRenderer>();
}
lineRenderer.startWidth = 0.001f;
lineRenderer.endWidth = 0.001f;
var rod = prefab.GetComponent<RodAsset>();
if (rod == null)
{
rod = prefab.AddComponent<RodAsset>();
}
rod.lineRenderer = lineRenderer;
rod.root = FindTransformsByNameContainsOnes(prefab.transform, "joint_root");
rod.LeftHandConnector = FindTransformsByNameContainsOnes(prefab.transform, "l_hand_connector");
rod.RightHandConnector = FindTransformsByNameContainsOnes(prefab.transform, "r_hand_connector");
rod.ReelConnector = FindTransformsByNameContainsOnes(prefab.transform, "reel_connector");
rod.gripEnd = FindTransformsByNameContainsOnes(prefab.transform, "grip_end");
var trans = prefab.GetComponentsInChildren<Transform>(true);
List<Transform> joints = new List<Transform>();
List<Transform> rings = new List<Transform>();
foreach (var tran in trans)
{
if (tran == null) continue;
if (tran == rod.root) continue;
if (tran.name.Contains("_RING_"))
{
rings.Add(tran);
}
else if (tran.name.Contains("_joint_"))
{
joints.Add(tran);
}
}
var blancEnd = FindTransformByName(prefab.transform, "blanc_end");
if (blancEnd == null)
{
Debug.LogError($"blanc_end 为空name={prefab.name}");
}
else
{
joints.Add(blancEnd);
}
rod.rings = rings.ToArray();
rod.joints = joints.ToArray();
var ccdIK = prefab.GetComponent<CCDIK>();
if (ccdIK == null)
{
ccdIK = prefab.AddComponent<CCDIK>();
}
var solver = ccdIK.solver;
if (solver != null)
{
solver.maxIterations = 3;
var rootField = solver.GetType().GetField("root",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
if (rootField != null)
{
rootField.SetValue(solver, prefab.transform);
}
solver.bones = Array.Empty<IKSolver.Bone>();
for (var i = 1; i < rod.joints.Length; i++)
{
solver.AddBone(rod.joints[i]);
}
}
EditorUtility.SetDirty(rod);
EditorUtility.SetDirty(ccdIK);
EditorUtility.SetDirty(prefab);
}
#endregion
#region 线
private static List<AnimationClip> _animationClips;
[MenuItem("Assets/Fix/修复线轴", false, 3)]
private static void FixReels()
{
_animationClips = GetAllClips();
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixReel(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复线轴失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixReel(GameObject prefab)
{
RemoveMissingScriptsFrom(prefab);
var reel = prefab.GetComponent<ReelAsset>();
if (reel == null)
{
reel = prefab.AddComponent<ReelAsset>();
}
reel.rootConnector = FindTransformsByNameContainsOnes(prefab.transform, "reel_root_connector");
reel.rootCompensator = FindTransformsByNameContainsOnes(prefab.transform, "reel_root_compensator");
reel.lineConnector = FindTransformsByNameContainsOnes(prefab.transform, "line_connector");
reel.lineIntersect = FindTransformsByNameContainsOnes(prefab.transform, "line_intersect");
reel.lineIntersectHelper = reel.lineIntersect.parent;
reel.handle = FindTransformsByNameContainsOnes(prefab.transform, "ik_locator_handle");
reel.handleEnd = reel.handle.parent;
var anim = reel.rootConnector.parent.GetComponent<Animator>();
if (anim == null)
{
anim = reel.rootConnector.parent.gameObject.AddComponent<Animator>();
}
reel.animator = anim;
// var anim = reel.rootConnector.parent.GetComponent<Animation>();
// if (anim == null)
// {
// anim = reel.rootConnector.parent.gameObject.AddComponent<Animation>();
// }
// List<AnimationClip> clips = _animationClips.Where(clip => clip.name.Contains(prefab.name)).ToList();
// foreach (var clip in clips)
// {
// anim.AddClip(clip, clip.name);
// var lowName = clip.name.ToLower();
// if (lowName.Contains("open"))
// {
// reel.openAnimation = clip;
// }
// else if (lowName.Contains("close"))
// {
// reel.closeAnimation = clip;
// }
// else if (lowName.Contains("handle_roll"))
// {
// reel.rollHandleAnimation = clip;
// }
// }
// anim.playAutomatically = true;
// reel.anim = anim;
}
#endregion
#region
[MenuItem("Assets/Fix/修复浮漂", false, 4)]
private static void FixBobbers()
{
_animationClips = GetAllClips();
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixBobber(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼漂失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixBobber(GameObject prefab)
{
// RemoveMissingScriptsFrom(prefab);
var bobber = prefab.GetComponent<BobberAsset>();
if (bobber == null)
{
bobber = prefab.AddComponent<BobberAsset>();
}
bobber.body = FindTransformsByNameContainsOnes(prefab.transform, "_body");
bobber.stick = FindTransformsByNameContainsOnes(prefab.transform, "_stick");
bobber.topConnector = FindTransformsByNameContainsOnes(prefab.transform, "_topConnector");
bobber.bottomConnector = FindTransformsByNameContainsOnes(prefab.transform, "_bottomConnector");
bobber.waterline = FindTransformsByNameContainsOnes(prefab.transform, "_waterline");
// var boxCollider = prefab.GetComponent<BoxCollider>();
// if (boxCollider != null)
// {
// DestroyImmediate(boxCollider);
// // boxCollider = prefab.AddComponent<BoxCollider>();
// }
//
// boxCollider.center = new Vector3(0, -0.01f, 0);
// boxCollider.size = new Vector3(0.005f, 0.005f, 0.005f);
var rigidbody = prefab.GetComponent<Rigidbody>();
if (rigidbody == null)
{
rigidbody = prefab.AddComponent<Rigidbody>();
}
rigidbody.useGravity = false;
var configurableJoint = prefab.GetComponent<ConfigurableJoint>();
if (configurableJoint == null)
{
configurableJoint = prefab.AddComponent<ConfigurableJoint>();
}
configurableJoint.xMotion = ConfigurableJointMotion.Locked;
configurableJoint.yMotion = ConfigurableJointMotion.Locked;
configurableJoint.zMotion = ConfigurableJointMotion.Locked;
}
#endregion
#region
[MenuItem("Assets/Fix/修复鱼钩", false, 5)]
private static void FixHooks()
{
_animationClips = GetAllClips();
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixHook(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼钩失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixHook(GameObject prefab)
{
// RemoveMissingScriptsFrom(prefab);
var hook = prefab.GetComponent<HookAsset>();
if (hook == null)
{
hook = prefab.AddComponent<HookAsset>();
}
hook.baitConnector = FindTransformsByNameContainsOnes(prefab.transform, "bait_connector");
var boxCollider = prefab.GetComponent<BoxCollider>();
if (boxCollider == null)
{
boxCollider = prefab.AddComponent<BoxCollider>();
}
boxCollider.center = new Vector3(0, -0.01f, 0);
boxCollider.size = new Vector3(0.005f, 0.005f, 0.005f);
var rigidbody = prefab.GetComponent<Rigidbody>();
if (rigidbody == null)
{
rigidbody = prefab.AddComponent<Rigidbody>();
}
rigidbody.useGravity = false;
var configurableJoint = prefab.GetComponent<ConfigurableJoint>();
if (configurableJoint == null)
{
configurableJoint = prefab.AddComponent<ConfigurableJoint>();
}
configurableJoint.xMotion = ConfigurableJointMotion.Locked;
configurableJoint.yMotion = ConfigurableJointMotion.Locked;
configurableJoint.zMotion = ConfigurableJointMotion.Locked;
}
#endregion
#region
[MenuItem("Assets/Fix/修复鱼饵", false, 6)]
private static void FixBaits()
{
_animationClips = GetAllClips();
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixBait(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼钩失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixBait(GameObject prefab)
{
var bait = prefab.GetComponent<BaitAsset>();
if (bait == null)
{
bait = prefab.AddComponent<BaitAsset>();
}
bait.hook = FindTransformsByNameContainsOnes(prefab.transform, "_hook");
}
#endregion
#region 仿
[MenuItem("Assets/Fix/修复路亚饵", false, 6)]
private static void FixLures()
{
_animationClips = GetAllClips();
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixLure(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼钩失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixLure(GameObject prefab)
{
RemoveMissingScriptsFrom(prefab);
var lure = prefab.GetComponent<LureAsset>();
if (lure == null)
{
lure = prefab.AddComponent<LureAsset>();
}
List<Transform> hookPoints = new List<Transform>();
for (int i = 1; i < 5; i++)
{
var hook = FindTransformByName(prefab.transform, $"hook_0{i}");
if (hook == null) break;
hookPoints.Add(hook);
}
lure.hookPoints = hookPoints.ToArray();
// hook_01
}
#endregion
#region
[MenuItem("Assets/Fix/修复鱼", false, 7)]
private static void FixFishs()
{
_animationClips = GetAllClips();
var rods = GetSelectPrefab<GameObject>();
foreach (var rod in rods)
{
try
{
FixFish(rod);
EditorUtility.SetDirty(rod);
}
catch (Exception e)
{
Debug.LogError($"修复鱼钩失败name={rod.name} e={e}");
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
private static void FixFish(GameObject prefab)
{
var bait = prefab.GetComponent<FishAsset>();
if (bait == null)
{
bait = prefab.AddComponent<FishAsset>();
}
}
#endregion
#region
private static List<AnimationClip> GetAllClips()
{
List<AnimationClip> list = new List<AnimationClip>();
// 获取项目中所有的AnimationClip
string[] guids = AssetDatabase.FindAssets("t:AnimationClip");
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
AnimationClip clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(path);
if (clip != null)
{
list.Add(clip);
}
}
return list;
}
private static string GetPathToParent(Transform currentTransform)
{
if (currentTransform == null || currentTransform.parent == null)
{
return string.Empty; // 如果没有父级,返回空字符串
}
// 递归调用先获取父级的路径然后加上当前Transform的名字
return GetPathToParent(currentTransform.parent) + "/" + currentTransform.name;
}
private static T FindFirstComponentInChildren<T>(GameObject parent) where T : Component
{
// 检查当前对象
T component = parent.GetComponent<T>();
if (component != null)
{
return component;
}
// 递归检查子对象
foreach (Transform child in parent.transform)
{
T result = FindFirstComponentInChildren<T>(child.gameObject);
if (result != null)
{
return result;
}
}
return null;
}
private static Transform FindTransformByName(Transform parent, string name)
{
// 检查当前对象
if (parent.name == name)
{
return parent;
}
// 递归检查子对象
foreach (Transform child in parent)
{
Transform result = FindTransformByName(child, name);
if (result != null)
{
return result;
}
}
return null;
}
/// <summary>
///
/// </summary>
/// <param name="parent"></param>
/// <param name="namePrefix"></param>
/// <returns></returns>
private static List<Transform> FindTransformsByNamePrefix(Transform parent, string namePrefix)
{
List<Transform> result = new List<Transform>();
// 检查当前对象
if (parent.name.StartsWith(namePrefix))
{
result.Add(parent);
}
// 递归检查子对象
foreach (Transform child in parent)
{
result.AddRange(FindTransformsByNamePrefix(child, namePrefix));
}
return result;
}
private static Transform FindTransformsByNameContainsOnes(Transform parent, string nameContains)
{
var trans = FindTransformsByNameContains(parent, nameContains);
if (trans != null && trans.Count > 0)
{
return trans.First();
}
return null;
}
/// <summary>
/// 获取首个包含制定名字的tran
/// </summary>
/// <param name="parent"></param>
/// <param name="nameContains"></param>
/// <returns></returns>
private static List<Transform> FindTransformsByNameContains(Transform parent, string nameContains)
{
List<Transform> result = new List<Transform>();
// 检查当前对象
if (parent.name.Contains(nameContains))
{
result.Add(parent);
}
// 递归检查子对象
foreach (Transform child in parent)
{
result.AddRange(FindTransformsByNameContains(child, nameContains));
}
return result;
}
private static T[] GetSelectPrefab<T>(string ext = ".prefab") where T : Object
{
// 获取当前选中的路径
string selectedPath = GetSelectedFolderPath();
if (string.IsNullOrEmpty(selectedPath))
{
Debug.LogWarning("No folder selected.");
return Array.Empty<T>();
}
List<T> list = new List<T>();
// 获取该文件夹中的所有资产路径
string[] assetGuids = AssetDatabase.FindAssets("", new[] { selectedPath });
foreach (string guid in assetGuids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
// 检查路径是否以 ".prefab" 结尾
if (path.EndsWith(ext))
{
var prefab = AssetDatabase.LoadAssetAtPath<T>(path);
if (prefab != null)
{
list.Add(prefab);
}
}
}
return list.ToArray();
}
/// <summary>
/// 移除missing的脚步
/// </summary>
/// <param name="objects"></param>
/// <returns></returns>
private static int RemoveMissingScriptsFrom(params GameObject[] objects)
{
List<GameObject> forceSave = new();
int removedCounter = 0;
foreach (GameObject current in objects)
{
if (current == null) continue;
int missingCount = GameObjectUtility.GetMonoBehavioursWithMissingScriptCount(current);
if (missingCount == 0) continue;
GameObjectUtility.RemoveMonoBehavioursWithMissingScript(current);
EditorUtility.SetDirty(current);
if (EditorUtility.IsPersistent(current) && PrefabUtility.IsAnyPrefabInstanceRoot(current))
forceSave.Add(current);
Debug.Log($"Removed {missingCount} Missing Scripts from {current.gameObject.name}", current);
removedCounter += missingCount;
}
foreach (GameObject o in forceSave) PrefabUtility.SavePrefabAsset(o);
return removedCounter;
}
/// <summary>
/// 获取选中的文件夹路径
/// </summary>
/// <returns></returns>
private static string GetSelectedFolderPath()
{
// 获取当前选中的对象
Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.Assets);
if (selection.Length > 0)
{
string path = AssetDatabase.GetAssetPath(selection[0]);
if (AssetDatabase.IsValidFolder(path))
{
return path;
}
}
return null;
}
/// <summary>
/// 在所有子对象中查找名字为childName的对象
/// </summary>
/// <param name="parent"></param>
/// <param name="childName"></param>
/// <returns></returns>
public static Transform FindDeepChild(Transform parent, string childName)
{
Transform result = parent.Find(childName);
if (result != null)
return result;
foreach (Transform child in parent)
{
result = FindDeepChild(child, childName);
if (result != null)
return result;
}
return null;
}
#endregion
}
}