首次提交

This commit is contained in:
Bob.Song
2026-03-05 18:07:55 +08:00
commit e125bb869e
4534 changed files with 563920 additions and 0 deletions

View File

@@ -0,0 +1,808 @@
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
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d55d4f69aaa14fb2910c88c7230d7273
timeCreated: 1743782400