forked from sin365/AxibugEmuOnline
完善AxiPoject工具
This commit is contained in:
parent
ebb4cb401c
commit
a1db47ab4b
@ -0,0 +1,42 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public class AxiProjectTools_AssetsAutoSetting : EditorWindow
|
||||
{
|
||||
[MenuItem("Axibug移植工具/AssetsAutoSetting/自动设置TextureMaxSize为图片大小1倍")]
|
||||
public static void AutoSettTextureSize_1x() { SetTextureSite(1f); }
|
||||
|
||||
[MenuItem("Axibug移植工具/AssetsAutoSetting/自动设置TextureMaxSize为图片大小2分之1倍")]
|
||||
public static void AutoSettTextureSize_1_2x() { SetTextureSite(1f / 2f); }
|
||||
[MenuItem("Axibug移植工具/AssetsAutoSetting/自动设置TextureMaxSize为图片大小4分之1倍")]
|
||||
public static void AutoSettTextureSize_1_4x() { SetTextureSite(1f / 4f); }
|
||||
|
||||
public static void SetTextureSite(float Scale)
|
||||
{
|
||||
Texture2D[] textures = Selection.GetFiltered<Texture2D>(SelectionMode.DeepAssets);
|
||||
if (textures.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("请先选择目录,或者Texture资源");
|
||||
return;
|
||||
}
|
||||
|
||||
AssetDatabase.StartAssetEditing(); // 开启批量编辑模式
|
||||
foreach (var texture in textures)
|
||||
{
|
||||
string path = AssetDatabase.GetAssetPath(texture);
|
||||
TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||
if (importer != null)
|
||||
{
|
||||
int size = Mathf.Max(texture.width, texture.height);
|
||||
int maxsize = Mathf.ClosestPowerOfTwo((int)(size * Scale)); // Unity内置方法适配2的幂次方
|
||||
importer.maxTextureSize = maxsize;
|
||||
importer.SaveAndReimport();
|
||||
}
|
||||
}
|
||||
AssetDatabase.StopAssetEditing(); // 结束批量编辑
|
||||
Debug.Log($"Updated {textures.Length} textures.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc0741a79e74f96449a260406f239066
|
||||
@ -0,0 +1,840 @@
|
||||
#if UNITY_EDITOR && UNITY_2020_1_OR_NEWER
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public class AxiProjectToolsStatistics : EditorWindow
|
||||
{
|
||||
static string cachecfgPath = "Assets/AxiStatisticsDatas.asset";
|
||||
static Dictionary<string, AxiStatisticsDatas> dictTempData = new Dictionary<string, AxiStatisticsDatas>();
|
||||
|
||||
static void ClearTempData()
|
||||
{
|
||||
dictTempData.Clear();
|
||||
}
|
||||
static string GetRootTempKey(int type, string rootName)
|
||||
{
|
||||
return type + "_" + rootName;
|
||||
}
|
||||
|
||||
|
||||
// 添加Hierarchy右键菜单项
|
||||
[MenuItem("GameObject/AxiStatistics/GetAxiNodeHash", false, 10)]
|
||||
public static void GetAxiNodeHash()
|
||||
{
|
||||
// 获取当前右键选中的Transform
|
||||
Transform selectedTransform = Selection.activeTransform;
|
||||
if (selectedTransform != null)
|
||||
{
|
||||
Debug.Log("选中的对象"+selectedTransform.name+",Hash=>"+ GetNodeDataHash(selectedTransform,true));
|
||||
}
|
||||
}
|
||||
|
||||
static int GetNodeDataHash(Transform trans,bool bLog = false)
|
||||
{
|
||||
long hashplus = 0;
|
||||
hashplus += trans.position.GetHashCode();
|
||||
hashplus += trans.localPosition.GetHashCode();
|
||||
|
||||
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
int count = trans.childCount;
|
||||
#else
|
||||
int count = trans.GetChildCount();
|
||||
#endif
|
||||
hashplus += count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
hashplus += trans.GetChild(i).name.GetHashCode();
|
||||
}
|
||||
|
||||
|
||||
if (bLog)
|
||||
{
|
||||
//Debug.Log("trans.position.GetHashCode()=>" + trans.position.GetHashCode());
|
||||
//Debug.Log("trans.localPosition.GetHashCode()=>" + trans.localPosition.GetHashCode());
|
||||
//Debug.Log("childCount =>" + count);
|
||||
//Debug.Log("hashplus =>" + hashplus);
|
||||
//Debug.Log("hashplus.GetHashCode() =>" + hashplus.GetHashCode());
|
||||
}
|
||||
|
||||
return hashplus.GetHashCode();
|
||||
}
|
||||
static int GetNodeLinkListHash(List<AxiStatistics_Node_Link> nodes)
|
||||
{
|
||||
string hashplus = string.Empty;
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
hashplus += node.Name;
|
||||
hashplus += node.Idx.ToString();
|
||||
}
|
||||
|
||||
return hashplus.GetHashCode();
|
||||
}
|
||||
|
||||
static string GetNodeLinkListStr(List<AxiStatistics_Node_Link> nodes)
|
||||
{
|
||||
string linkstr = string.Empty;
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
linkstr += "/";
|
||||
linkstr += node.Name;
|
||||
linkstr += "[" + node.Idx + "]";
|
||||
}
|
||||
return linkstr;
|
||||
}
|
||||
|
||||
static void AddComponentData(int _type, string _rootPath, AxiStatistics_Node_Component _comdata, string _nodepath, Component lastcom)
|
||||
{
|
||||
string rootKey = GetRootTempKey(_type, _rootPath);
|
||||
|
||||
if (!dictTempData.ContainsKey(rootKey))
|
||||
{
|
||||
dictTempData[rootKey] = new AxiStatisticsDatas() { type = _type, FullPath = _rootPath, nodes = new List<AxiStatistics_Node>() };
|
||||
}
|
||||
AxiStatisticsDatas rootData = dictTempData[rootKey];
|
||||
|
||||
List<AxiStatistics_Node_Link> link = new List<AxiStatistics_Node_Link>();
|
||||
if (lastcom.transform.parent != null)
|
||||
{
|
||||
Transform currNode = lastcom.transform;
|
||||
while (currNode != null)
|
||||
{
|
||||
//最顶层了
|
||||
if (currNode.parent == null)
|
||||
{
|
||||
link.Insert(0, new AxiStatistics_Node_Link()
|
||||
{
|
||||
NodeHash = GetNodeDataHash(currNode),
|
||||
Idx = 0,
|
||||
OnlyOne = true,
|
||||
Name = currNode.gameObject.name
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
int thisNameAllCount = 0;
|
||||
int thisNodeIdx = -1;
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
int count = currNode.parent.childCount;
|
||||
#else
|
||||
int count = currNode.parent.GetChildCount();
|
||||
#endif
|
||||
bool bFind = false;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
GameObject checkGobj = currNode.parent.GetChild(i).gameObject;
|
||||
if (checkGobj.name == currNode.name)
|
||||
{
|
||||
thisNameAllCount++;
|
||||
if (checkGobj == currNode.gameObject)
|
||||
{
|
||||
thisNodeIdx = thisNameAllCount - 1;
|
||||
bFind = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bFind)
|
||||
{
|
||||
link.Insert(0, new AxiStatistics_Node_Link()
|
||||
{
|
||||
NodeHash = GetNodeDataHash(currNode),
|
||||
Idx = thisNodeIdx,
|
||||
OnlyOne = thisNameAllCount == 1,
|
||||
Name = currNode.gameObject.name
|
||||
});
|
||||
currNode = currNode.parent;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
link.Insert(0, new AxiStatistics_Node_Link()
|
||||
{
|
||||
NodeHash = GetNodeDataHash(lastcom.transform),
|
||||
Idx = 0,
|
||||
OnlyOne = true,
|
||||
Name = lastcom.gameObject.name
|
||||
});
|
||||
}
|
||||
|
||||
int linkhash = GetNodeLinkListHash(link);
|
||||
AxiStatistics_Node nodeData = rootData.nodes.Where(w => w.LinkHash == linkhash).FirstOrDefault();
|
||||
if (nodeData == null)
|
||||
{
|
||||
nodeData = new AxiStatistics_Node();
|
||||
nodeData.Name = Path.GetFileName(_nodepath);
|
||||
//nodeData.NodeFullPath = _nodepath;
|
||||
nodeData.components = new List<AxiStatistics_Node_Component>();
|
||||
//nodeData.NodeIdx = thisNodeIdx;
|
||||
//nodeData.NodeIdxOnlyOne = bNodeIdxOnlyOne;
|
||||
|
||||
nodeData.link = link;
|
||||
nodeData.LinkHash = linkhash;
|
||||
nodeData.LinkFullStr = GetNodeLinkListStr(link);
|
||||
|
||||
rootData.nodes.Add(nodeData);
|
||||
}
|
||||
|
||||
nodeData.components.Add(_comdata);
|
||||
}
|
||||
|
||||
static bool CheckCom(Component[] allcoms, int comRealIdx, int _type, string _rootPath, Component com, string nodepath)
|
||||
{
|
||||
if (com is BoxCollider2D)
|
||||
{
|
||||
BoxCollider2D bc = com as BoxCollider2D;
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
Debug.Log(nodepath + "BoxCollider2D->center=>(" + bc.offset.x + "," + bc.offset.y + ") size=>(" + bc.size.x + "," + bc.size.y + "");
|
||||
#else
|
||||
Debug.Log(nodepath +"BoxCollider2D->center=>("+ bc.center.x+","+bc.center.y+") size=>("+ bc.size.x+","+bc.size.y+"");
|
||||
#endif
|
||||
AxiStatistics_Node_Component _com = new AxiStatistics_Node_Component();
|
||||
_com.type = typeof(BoxCollider2D).ToString();
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
_com.center = bc.offset;
|
||||
#else
|
||||
_com.center = bc.center;
|
||||
#endif
|
||||
_com.size = bc.size;
|
||||
SetCompnentIdxNum<BoxCollider2D>(_com, allcoms, comRealIdx, bc);
|
||||
AddComponentData(_type, _rootPath, _com, nodepath, com);
|
||||
}
|
||||
if (com is Rigidbody2D)
|
||||
{
|
||||
Rigidbody2D rig2d = com as Rigidbody2D;
|
||||
Debug.Log(_rootPath + "Rigidbody2D->simulated=>(" + rig2d.simulated + ")");
|
||||
Debug.Log(_rootPath + "Rigidbody2D->IsSleeping=>(" + rig2d.isKinematic.ToString() + ")");
|
||||
|
||||
AxiStatistics_Node_Component _com = new AxiStatistics_Node_Component();
|
||||
_com.type = typeof(Rigidbody2D).ToString();
|
||||
_com.isKinematic = rig2d.isKinematic;
|
||||
_com.simulated = rig2d.simulated;
|
||||
_com.gravityScale = rig2d.gravityScale;
|
||||
SetCompnentIdxNum<Rigidbody2D>(_com, allcoms, comRealIdx, rig2d);
|
||||
AddComponentData(_type, _rootPath, _com, nodepath, com);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 找出同类Idx
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="allcoms"></param>
|
||||
/// <param name="comRealIdx"></param>
|
||||
/// <param name="com"></param>
|
||||
/// <returns></returns>
|
||||
static void SetCompnentIdxNum<T>(AxiStatistics_Node_Component _comData, Component[] allcoms, int comRealIdx, T com) where T : Component
|
||||
{
|
||||
int ComIdxNum;
|
||||
bool ComTypeIsOnlyOne = false;
|
||||
int TCount = com.transform.GetComponents<T>().Length;
|
||||
if (TCount == 1)
|
||||
{
|
||||
ComIdxNum = 0;
|
||||
ComTypeIsOnlyOne = true;
|
||||
}
|
||||
else if (TCount < 1)
|
||||
{
|
||||
Debug.LogError("找不到,不应该");
|
||||
ComIdxNum = -1;
|
||||
}
|
||||
|
||||
ComIdxNum = -1;
|
||||
for (int i = 0; i < allcoms.Length; i++)
|
||||
{
|
||||
//他自己自然是了
|
||||
if (i == comRealIdx)
|
||||
{
|
||||
ComIdxNum++;
|
||||
break;
|
||||
}
|
||||
if (allcoms[i] is T)
|
||||
ComIdxNum++;
|
||||
}
|
||||
|
||||
_comData.ComIdxNum = ComIdxNum;
|
||||
_comData.ComTypeOnlyOne = ComTypeIsOnlyOne;
|
||||
}
|
||||
|
||||
[MenuItem("Axibug移植工具/Statistics/[1]统计所有预制体和场景下的Collider和RigBody")]
|
||||
|
||||
public static void StatisticsCollider()
|
||||
{
|
||||
ClearTempData();
|
||||
StatisticsCollider<BoxCollider2D>();
|
||||
StatisticsCollider<Rigidbody2D>();
|
||||
|
||||
AxiStatisticsCache cache = ScriptableObject.CreateInstance<AxiStatisticsCache>();
|
||||
foreach (var data in dictTempData)
|
||||
cache.caches.Add(data.Value);
|
||||
AssetDatabase.CreateAsset(cache, cachecfgPath);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
public static void StatisticsCollider<T>() where T : Component
|
||||
{
|
||||
AxiProjectTools.GoTAxiProjectToolsSence();
|
||||
|
||||
string[] sceneGuids = AssetDatabase.FindAssets("t:scene");
|
||||
foreach (string guid in sceneGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains(AxiProjectTools.toolSenceName))
|
||||
continue;
|
||||
|
||||
#if UNITY_4_6
|
||||
EditorApplication.OpenScene(path);
|
||||
#else
|
||||
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(path);
|
||||
#endif
|
||||
|
||||
// 创建一个列表来存储根节点
|
||||
List<GameObject> rootNodes = new List<GameObject>();
|
||||
|
||||
// 遍历场景中的所有对象
|
||||
GameObject[] allObjects = FindObjectsOfType<GameObject>();
|
||||
foreach (GameObject obj in allObjects)
|
||||
{
|
||||
// 检查对象是否有父对象
|
||||
if (obj.transform.parent == null)
|
||||
{
|
||||
// 如果没有父对象,则它是一个根节点
|
||||
rootNodes.Add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var node in rootNodes)
|
||||
LoopPrefabNode<T>(0, path, path, node, 0);
|
||||
|
||||
}
|
||||
string[] prefabGuids = AssetDatabase.FindAssets("t:Prefab");
|
||||
foreach (string guid in prefabGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
GetPrefab<T>(path);
|
||||
}
|
||||
|
||||
AxiProjectTools.GoTAxiProjectToolsSence();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 统计所有预制体和场景下的" + typeof(T).FullName + "</color>");
|
||||
}
|
||||
|
||||
static void GetPrefab<T>(string path) where T : Component
|
||||
{
|
||||
#if UNITY_4_6
|
||||
GameObject prefab = AssetDatabase.LoadAssetAtPath(path,typeof(GameObject)) as GameObject;
|
||||
#else
|
||||
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
||||
#endif
|
||||
|
||||
LoopPrefabNode<T>(1, path, path, prefab.gameObject, 0);
|
||||
}
|
||||
|
||||
static void LoopPrefabNode<T>(int _type, string _rootPath, string noderootPath, GameObject trans, int depth) where T : Component
|
||||
{
|
||||
// #if UNITY_2018_4_OR_NEWER
|
||||
string nodename = noderootPath + "/" + trans.name;
|
||||
GameObject prefabRoot = trans.gameObject;
|
||||
|
||||
Component[] components = prefabRoot.GetComponents<Component>();
|
||||
for (int i = 0; i < components.Length; i++)
|
||||
{
|
||||
var com = components[i];
|
||||
|
||||
if (com == null)
|
||||
continue;
|
||||
|
||||
T comobj = com as T;
|
||||
if (comobj == null)
|
||||
continue;
|
||||
|
||||
if (CheckCom(components, i, _type, _rootPath, comobj, nodename))
|
||||
continue;
|
||||
}
|
||||
|
||||
//遍历
|
||||
foreach (Transform child in trans.transform)
|
||||
LoopPrefabNode<T>(_type, _rootPath, nodename, child.gameObject, depth + 1);
|
||||
//#else
|
||||
// Debug.Log("低版本不要执行本函数");
|
||||
//#endif
|
||||
}
|
||||
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
[MenuItem("Axibug移植工具/Statistics/[2]通过记录,对组件进行修补")]
|
||||
public static void RepairRigBodyByStatistics()
|
||||
{
|
||||
List<string> errLog = new List<string>();
|
||||
List<string> doneLog = new List<string>();
|
||||
List<ValueTuple<string, string>> NeedRepair = new List<ValueTuple<string, string>>();
|
||||
List<ValueTuple<string, string>> FinishRepair = new List<ValueTuple<string, string>>();
|
||||
string CurrScenePath = string.Empty;
|
||||
AxiProjectTools.GoTAxiProjectToolsSence();
|
||||
#if UNITY_4_6
|
||||
AxiStatisticsCache data = AssetDatabase.LoadAssetAtPath(cachecfgPath,typeof(AxiStatisticsCache)) as AxiStatisticsCache;
|
||||
#else
|
||||
AxiStatisticsCache data = AssetDatabase.LoadAssetAtPath<AxiStatisticsCache>(cachecfgPath);
|
||||
#endif
|
||||
string[] sceneGuids = AssetDatabase.FindAssets("t:scene");
|
||||
List<string> ScenePath = new List<string>();
|
||||
List<string> SceneName = new List<string>();
|
||||
foreach (string guid in sceneGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains(AxiProjectTools.toolSenceName))
|
||||
continue;
|
||||
ScenePath.Add(path);
|
||||
SceneName.Add(Path.GetFileName(path));
|
||||
}
|
||||
|
||||
string[] prefabGuids = AssetDatabase.FindAssets("t:prefab");
|
||||
List<string> prefabPath = new List<string>();
|
||||
List<string> prefabName = new List<string>();
|
||||
foreach (string guid in prefabGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
prefabPath.Add(path);
|
||||
prefabName.Add(Path.GetFileName(path));
|
||||
}
|
||||
|
||||
foreach (var cache in data.caches.OrderBy(w => w.type))
|
||||
{
|
||||
//场景
|
||||
if (cache.type == 0)
|
||||
{
|
||||
#region 场景加载
|
||||
string targetName = Path.GetFileName(cache.FullPath);
|
||||
int Idx = SceneName.IndexOf(targetName);
|
||||
if (Idx < 0)
|
||||
{
|
||||
Debug.LogError(targetName + "[Repair]找不到对应资源");
|
||||
continue;
|
||||
}
|
||||
string targetpath = ScenePath[Idx];
|
||||
|
||||
//保证场景切换
|
||||
if (!string.Equals(CurrScenePath, targetpath))
|
||||
{
|
||||
#if UNITY_4_6
|
||||
EditorApplication.OpenScene(targetpath);
|
||||
#else
|
||||
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(targetpath);
|
||||
#endif
|
||||
}
|
||||
CurrScenePath = targetpath;
|
||||
#endregion
|
||||
|
||||
int DirtyCount = 0;
|
||||
foreach (var node in cache.nodes)
|
||||
{
|
||||
GameObject targetNodePathObj = GetNodeByLink(cache.FullPath, node.link, out string errStr);
|
||||
if (targetNodePathObj == null)
|
||||
{
|
||||
errLog.Add(errStr);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
string targetNodePath = node.NodeFullPath.Substring(cache.FullPath.Length, node.NodeFullPath.Length - cache.FullPath.Length);
|
||||
|
||||
//GameObject targetNodePathObj = GameObject.Find(targetNodePath);
|
||||
GameObject targetNodePathObj = GetNodeByIdx(node, targetNodePath);
|
||||
|
||||
if (targetNodePathObj == null)
|
||||
{
|
||||
string err = "[Repair]" + node.NodeFullPath + "找不到对应节点";
|
||||
errLog.Add(err);
|
||||
Debug.LogError(err);
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
foreach (var com in node.components)
|
||||
{
|
||||
if (RepairComponent(node.LinkFullStr, targetNodePathObj, com, out var errlog))
|
||||
{
|
||||
NeedRepair.Add(new ValueTuple<string, string>($"{cache.FullPath}:{node.LinkFullStr}", $"{com.type}[{com.ComIdxNum}]"));
|
||||
DirtyCount++;
|
||||
}
|
||||
errLog.AddRange(errlog);
|
||||
}
|
||||
}
|
||||
if (DirtyCount > 0)
|
||||
{
|
||||
Debug.Log($"[Repair][场景处理]{cache.FullPath}共{DirtyCount}个需要处理");
|
||||
|
||||
|
||||
// 获取当前打开的场景
|
||||
var activeScene = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene();
|
||||
|
||||
// 保存场景
|
||||
UnityEditor.SceneManagement.EditorSceneManager.SaveScene(activeScene);
|
||||
|
||||
Debug.Log("场景已保存: " + activeScene.path);
|
||||
string donestr = $"[Repair][场景处理成功]{targetpath},共{DirtyCount}个";
|
||||
doneLog.Add(donestr);
|
||||
|
||||
}
|
||||
}
|
||||
else if (cache.type == 1)
|
||||
{
|
||||
string targetpath = cache.FullPath;
|
||||
|
||||
//来到空场景
|
||||
if (!string.IsNullOrEmpty(CurrScenePath))
|
||||
{
|
||||
AxiProjectTools.GoTAxiProjectToolsSence();
|
||||
CurrScenePath = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
GameObject prefabInstance = AssetDatabase.LoadAssetAtPath<GameObject>(targetpath);
|
||||
if (prefabInstance == null)
|
||||
{
|
||||
Debug.LogError($"[Repair]Failed to load prefab at path: {prefabPath}");
|
||||
return;
|
||||
}
|
||||
|
||||
var obj = GameObject.Instantiate(prefabInstance, null);
|
||||
|
||||
int DirtyCount = 0;
|
||||
foreach (var node in cache.nodes)
|
||||
{
|
||||
GameObject targetNodePathObj = GetNodeByLink(cache.FullPath, node.link, out string errStr, obj);
|
||||
|
||||
if (targetNodePathObj == null)
|
||||
{
|
||||
errLog.Add(errStr);
|
||||
continue;
|
||||
}
|
||||
//if (node.NodeFullPath == targetpath + "/" + Path.GetFileNameWithoutExtension(targetpath))
|
||||
//{
|
||||
// //预制体自己就是目标
|
||||
// targetNodePathObj = obj;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// string targetNodePath = node.NodeFullPath.Substring(cache.FullPath.Length + prefabInstance.name.Length + 2, node.NodeFullPath.Length - cache.FullPath.Length - prefabInstance.name.Length - 2);
|
||||
// //targetNodePathObj = obj.transform.Find(targetNodePath)?.gameObject;
|
||||
// targetNodePathObj = GetNodeByIdx(node, targetNodePath, obj);
|
||||
|
||||
// if (targetNodePathObj == null)
|
||||
// {
|
||||
// Debug.LogError("[Repair]" + targetNodePath + "找不到对应节点");
|
||||
// continue;
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
foreach (var com in node.components)
|
||||
{
|
||||
if (RepairComponent(node.LinkFullStr, targetNodePathObj, com, out var errlog))
|
||||
{
|
||||
NeedRepair.Add(new ValueTuple<string, string>($"{cache.FullPath}:{node.LinkFullStr}", $"{com.type}[{com.ComIdxNum}]"));
|
||||
DirtyCount++;
|
||||
}
|
||||
|
||||
errLog.AddRange(errlog);
|
||||
}
|
||||
}
|
||||
|
||||
if (DirtyCount > 0)
|
||||
{
|
||||
Debug.Log($"[Repair][预制体处理]{targetpath}共{DirtyCount}个需要处理");
|
||||
PrefabUtility.SaveAsPrefabAsset(obj, targetpath);
|
||||
string donestr = $"[Repair][预制体处理成功]{targetpath},共{DirtyCount}个";
|
||||
doneLog.Add(donestr);
|
||||
}
|
||||
GameObject.DestroyImmediate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
AxiProjectTools.GoTAxiProjectToolsSence();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("[Repair][统计]:");
|
||||
sb.AppendLine("----处理成功----");
|
||||
foreach (var val in doneLog.OrderBy(w => w))
|
||||
{
|
||||
sb.AppendLine(val);
|
||||
}
|
||||
sb.AppendLine("----异常统计----");
|
||||
foreach (var val in errLog.OrderBy(w => w))
|
||||
{
|
||||
sb.AppendLine(val);
|
||||
}
|
||||
sb.AppendLine("----需要处理----");
|
||||
foreach (var val in NeedRepair.OrderBy(w => w.Item1))
|
||||
{
|
||||
sb.AppendLine($"{val.Item1}=>{val.Item2}");
|
||||
}
|
||||
Debug.Log($"{sb}");
|
||||
|
||||
File.WriteAllText("Assets/AxiNeedRepair.txt", sb.ToString());
|
||||
}
|
||||
|
||||
|
||||
// static GameObject GetNodeByIdx(AxiStatistics_Node nodedata, string targetNodePath, GameObject root = null)
|
||||
// {
|
||||
// GameObject targetNodePathObj;
|
||||
|
||||
// if (root == null)
|
||||
// targetNodePathObj = GameObject.Find(targetNodePath);
|
||||
// else
|
||||
// targetNodePathObj = root.transform.Find(targetNodePath)?.gameObject;
|
||||
|
||||
// if (targetNodePathObj == null)
|
||||
// return null;
|
||||
|
||||
// string targetName = targetNodePathObj.name;
|
||||
// int currIdx = -1;
|
||||
// if (!nodedata.NodeIdxOnlyOne)
|
||||
// {
|
||||
// if (targetNodePathObj.transform.parent != null)
|
||||
// {
|
||||
//#if UNITY_2017_1_OR_NEWER
|
||||
// int count = targetNodePathObj.transform.parent.childCount;
|
||||
//#else
|
||||
// int count = targetNodePathObj.transform.parent.GetChildCount();
|
||||
//#endif
|
||||
// for (int i = 0; i < count; i++)
|
||||
// {
|
||||
// GameObject checkGobj = targetNodePathObj.transform.parent.GetChild(i).gameObject;
|
||||
// if (checkGobj.name == targetName)
|
||||
// {
|
||||
// currIdx++;
|
||||
// if (nodedata.NodeIdx == currIdx)
|
||||
// {
|
||||
// targetNodePathObj = checkGobj;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return targetNodePathObj;
|
||||
// }
|
||||
|
||||
|
||||
static GameObject GetNodeByLink(string rootPath, List<AxiStatistics_Node_Link> linklist, out string errStr, GameObject PrefabRoot = null)
|
||||
{
|
||||
List<AxiStatistics_Node_Link> temp_useddlink = new List<AxiStatistics_Node_Link>();
|
||||
if (linklist.Count < 1)
|
||||
{
|
||||
errStr = $"[Repair] Link 为空";
|
||||
Debug.LogError(errStr);
|
||||
return null;
|
||||
}
|
||||
|
||||
temp_useddlink.Add(linklist[0]);
|
||||
GameObject currRoot;
|
||||
|
||||
if (PrefabRoot == null)
|
||||
currRoot = GameObject.Find(linklist[0].Name);
|
||||
else
|
||||
{
|
||||
currRoot = PrefabRoot;
|
||||
//currRoot = PrefabRoot.transform.Find(linklist[0].Name)?.gameObject;
|
||||
}
|
||||
|
||||
if (currRoot == null)
|
||||
{
|
||||
errStr = $"[Repair] 根节点找不到{rootPath}:{GetNodeLinkListStr(linklist)} => null";
|
||||
Debug.LogError(errStr);
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int link_i = 1; link_i < linklist.Count; link_i++)
|
||||
{
|
||||
AxiStatistics_Node_Link targetLink = linklist[link_i];
|
||||
temp_useddlink.Add(targetLink);
|
||||
GameObject findNode = null;
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
int count = currRoot.transform.childCount;
|
||||
#else
|
||||
int count = currNode.transform.GetChildCount();
|
||||
#endif
|
||||
|
||||
if (targetLink.OnlyOne)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
GameObject checkGobj = currRoot.transform.GetChild(i).gameObject;
|
||||
if (checkGobj.name == targetLink.Name)
|
||||
{
|
||||
findNode = checkGobj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Dictionary<int, GameObject> tempHash2Node = new Dictionary<int, GameObject>();
|
||||
List<GameObject> tempGobjList = new List<GameObject>();
|
||||
bool HashDrity = false;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
GameObject checkGobj = currRoot.transform.GetChild(i).gameObject;
|
||||
if (checkGobj.name == targetLink.Name)
|
||||
{
|
||||
int temphash = GetNodeDataHash(checkGobj.transform);
|
||||
if (!tempHash2Node.ContainsKey(temphash))
|
||||
{
|
||||
tempHash2Node.Add(GetNodeDataHash(checkGobj.transform), checkGobj);
|
||||
}
|
||||
else
|
||||
{
|
||||
HashDrity = true;
|
||||
}
|
||||
tempGobjList.Add(checkGobj);
|
||||
}
|
||||
}
|
||||
|
||||
//Hash严格模式
|
||||
if (!HashDrity && tempHash2Node.TryGetValue(targetLink.NodeHash, out var val))
|
||||
{
|
||||
findNode = val;
|
||||
}
|
||||
//下标模式
|
||||
else
|
||||
{
|
||||
if (targetLink.Idx < 0 || tempGobjList.Count == 0 || (tempGobjList.Count != 0 && targetLink.Idx >= tempGobjList.Count))
|
||||
{
|
||||
errStr = $"[Repair]link 下标模式 找不到=>{rootPath}:{GetNodeLinkListStr(temp_useddlink)}[{targetLink.Idx}] => 完整链路{rootPath}:{GetNodeLinkListStr(linklist)}";
|
||||
Debug.LogError(errStr);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
findNode = tempGobjList[targetLink.Idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
currRoot = findNode;
|
||||
if (currRoot == null)
|
||||
break;
|
||||
}
|
||||
|
||||
if (currRoot == null)
|
||||
{
|
||||
errStr = $"[Repair]link 找不到[{rootPath}:{GetNodeLinkListStr(temp_useddlink)}] => 完整链路{rootPath}:{GetNodeLinkListStr(linklist)}";
|
||||
Debug.LogError(errStr);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
errStr = string.Empty;
|
||||
return currRoot;
|
||||
}
|
||||
}
|
||||
|
||||
static bool RepairComponent(string NodePath, GameObject targetNodePathObj, AxiStatistics_Node_Component comdata, out List<string> Errlog)
|
||||
{
|
||||
Errlog = new List<string>();
|
||||
string err;
|
||||
bool Dirty = false;
|
||||
if (comdata.type == typeof(Rigidbody2D).ToString())
|
||||
{
|
||||
Rigidbody2D rg2d = GetCompnentById<Rigidbody2D>(targetNodePathObj, comdata);
|
||||
if (rg2d == null)
|
||||
{
|
||||
err = $"[Repair]{NodePath}=> Rigidbody2D[{comdata.ComIdxNum}] == null";
|
||||
Debug.LogError(err);
|
||||
Errlog.Add(err);
|
||||
Dirty = false;
|
||||
}
|
||||
|
||||
/*
|
||||
与新版Unity的差异
|
||||
无BodyType选项:Unity 4.6.7中所有Rigidbody2D默认等效于新版的Dynamic类型(受重力影响),但无法设置为Static或Kinematic。
|
||||
无Simulated选项:只要物体启用了Rigidbody2D组件且Gravity Scale > 0,就会受重力作用。
|
||||
|
||||
所以,一旦老版本gravityScale > 0,就受重力作用,直接设置新版本这边:simulated = true;bodyType = RigidbodyType2D.Dynamic;
|
||||
*/
|
||||
|
||||
|
||||
if (rg2d.gravityScale != comdata.gravityScale)
|
||||
{
|
||||
Debug.Log($"[Repair]{NodePath}=> Rigidbody2D[{comdata.ComIdxNum}] simulated:{rg2d.gravityScale} != :{comdata.gravityScale} rg2d.bodyType => {rg2d.bodyType} ");
|
||||
|
||||
rg2d.gravityScale = comdata.gravityScale;
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
//if (rg2d.gravityScale > 0 && (!rg2d.simulated || rg2d.bodyType != RigidbodyType2D.Dynamic))
|
||||
if (!rg2d.simulated || rg2d.bodyType != RigidbodyType2D.Dynamic)
|
||||
{
|
||||
Debug.Log($"[Repair]{NodePath}=> Rigidbody2D[{comdata.ComIdxNum}] simulated:{rg2d.simulated} != :{comdata.simulated} rg2d.bodyType => {rg2d.bodyType} ");
|
||||
|
||||
rg2d.simulated = true;
|
||||
rg2d.bodyType = RigidbodyType2D.Dynamic;
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
else if (comdata.type == typeof(BoxCollider2D).ToString())
|
||||
{
|
||||
BoxCollider2D bc = GetCompnentById<BoxCollider2D>(targetNodePathObj, comdata);
|
||||
if (bc == null)
|
||||
{
|
||||
err = $"[Repair]{NodePath}=> BoxCollider2D[{comdata.ComIdxNum}] == null";
|
||||
Debug.LogError(err);
|
||||
Errlog.Add(err);
|
||||
Dirty = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bc.size != comdata.size)
|
||||
{
|
||||
Debug.Log($"[Repair]{NodePath} BoxCollider2D[{comdata.ComIdxNum}] => size:{bc.size} != {comdata.size} ");
|
||||
bc.size = comdata.size;
|
||||
Dirty = true;
|
||||
}
|
||||
if (bc.offset != comdata.center)
|
||||
{
|
||||
Debug.Log($"[Repair]{NodePath} BoxCollider2D[{comdata.ComIdxNum}] => offset:{bc.offset} != center{comdata.center} ");
|
||||
bc.offset = comdata.center;
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
if (Dirty)
|
||||
{
|
||||
bc.size = comdata.size;
|
||||
bc.offset = comdata.center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Dirty;
|
||||
}
|
||||
|
||||
static T GetCompnentById<T>(GameObject gobj, AxiStatistics_Node_Component node) where T : Component
|
||||
{
|
||||
if (node.ComIdxNum == 0)
|
||||
return gobj.GetComponent<T>();
|
||||
else if (node.ComIdxNum > 0)
|
||||
{
|
||||
T[] coms = gobj.GetComponents<T>();
|
||||
if (node.ComIdxNum < coms.Length)
|
||||
return coms[node.ComIdxNum];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32aabdd304d2c4d47b8ef660f672ead1
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@ -3,19 +3,18 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public class AxiProjectTools : EditorWindow
|
||||
{
|
||||
static string cachecfgPath = "Assets/AxiComToolCache.asset";
|
||||
static string toolSenceName = "AxiProjectTools";
|
||||
static string outCsDir = Application.dataPath + "/AxiCom/";
|
||||
static Dictionary<string, AxiPrefabCache_Com2GUID> ComType2GUID = new Dictionary<string, AxiPrefabCache_Com2GUID>();
|
||||
|
||||
static void GoTAxiProjectToolsSence()
|
||||
public static string toolSenceName = "AxiProjectTools";
|
||||
public static string outCsDir = Application.dataPath + "/AxiCom/";
|
||||
public static Dictionary<string, AxiPrefabCache_Com2GUID> ComType2GUID = new Dictionary<string, AxiPrefabCache_Com2GUID>();
|
||||
|
||||
public static void GoTAxiProjectToolsSence()
|
||||
{
|
||||
string[] sceneGuids = AssetDatabase.FindAssets("t:scene");
|
||||
foreach (string guid in sceneGuids)
|
||||
@ -23,12 +22,16 @@ public class AxiProjectTools : EditorWindow
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains(toolSenceName))
|
||||
{
|
||||
EditorSceneManager.OpenScene(path);
|
||||
#if UNITY_4_6
|
||||
EditorApplication.OpenScene(path);
|
||||
#else
|
||||
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(path);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[1]采集所有预制体和场景下的UGUI组件")]
|
||||
public static void Part1()
|
||||
{
|
||||
@ -40,12 +43,16 @@ public class AxiProjectTools : EditorWindow
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains(toolSenceName))
|
||||
continue;
|
||||
|
||||
EditorSceneManager.OpenScene(path);
|
||||
|
||||
|
||||
#if UNITY_4_6
|
||||
EditorApplication.OpenScene(path);
|
||||
#else
|
||||
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(path);
|
||||
#endif
|
||||
|
||||
// 创建一个列表来存储根节点
|
||||
List<GameObject> rootNodes = new List<GameObject>();
|
||||
|
||||
|
||||
// 遍历场景中的所有对象
|
||||
GameObject[] allObjects = FindObjectsOfType<GameObject>();
|
||||
foreach (GameObject obj in allObjects)
|
||||
@ -57,19 +64,19 @@ public class AxiProjectTools : EditorWindow
|
||||
rootNodes.Add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (var node in rootNodes)
|
||||
LoopPrefabNode(path, node, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
string[] prefabGuids = AssetDatabase.FindAssets("t:Prefab");
|
||||
foreach (string guid in prefabGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
GetPrefab(path);
|
||||
}
|
||||
|
||||
|
||||
AxiPrefabCache cache = ScriptableObject.CreateInstance<AxiPrefabCache>();
|
||||
foreach (var data in ComType2GUID)
|
||||
cache.caches.Add(data.Value);
|
||||
@ -79,66 +86,88 @@ public class AxiProjectTools : EditorWindow
|
||||
GoTAxiProjectToolsSence();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [1]采集所有预制体和场景下的UGUI组件</color>");
|
||||
}
|
||||
|
||||
|
||||
static void GetPrefab(string path)
|
||||
{
|
||||
{
|
||||
#if UNITY_4_6
|
||||
GameObject prefab = AssetDatabase.LoadAssetAtPath(path,typeof(GameObject)) as GameObject;
|
||||
#else
|
||||
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
||||
#endif
|
||||
|
||||
LoopPrefabNode(path, prefab.gameObject, 0);
|
||||
}
|
||||
static void LoopPrefabNode(string rootPath, GameObject trans, int depth)
|
||||
{
|
||||
string nodename = $"{rootPath}>{trans.name}";
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
GameObject prefabRoot = trans.gameObject;
|
||||
int comCount = prefabRoot.GetComponentCount();
|
||||
for (int i = 0; i < comCount; i++)
|
||||
{
|
||||
var com = prefabRoot.GetComponentAtIndex(i);
|
||||
if (com == null)
|
||||
continue;
|
||||
|
||||
MonoBehaviour monoCom = com as MonoBehaviour;
|
||||
if (monoCom == null)
|
||||
continue;
|
||||
Type monoType = monoCom.GetType();
|
||||
if (!monoType.Assembly.FullName.Contains("UnityEngine.UI"))
|
||||
continue;
|
||||
// 获取MonoScript资源
|
||||
MonoScript monoScript = MonoScript.FromMonoBehaviour(monoCom);
|
||||
if (monoScript != null)
|
||||
{
|
||||
// 获取MonoScript资源的GUID
|
||||
string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(monoScript));
|
||||
Debug.Log($"{nodename} | <color=#FFF333>[{monoType.Name}]</color> <color=#FF0000>{guid}</color><color=#00FF00>({monoType.FullName})</color>");
|
||||
ComType2GUID[monoType.FullName] =
|
||||
new AxiPrefabCache_Com2GUID()
|
||||
{
|
||||
SrcFullName = monoType.FullName,
|
||||
SrcName = monoType.Name,
|
||||
GUID = guid,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("!!!! 没得");
|
||||
}
|
||||
}
|
||||
|
||||
//遍历
|
||||
foreach (Transform child in trans.transform)
|
||||
LoopPrefabNode(nodename, child.gameObject, depth + 1);
|
||||
#else
|
||||
Debug.Log("低版本不要执行本函数");
|
||||
#endif
|
||||
// #if UNITY_2018_4_OR_NEWER
|
||||
string nodename = rootPath + trans.name;
|
||||
GameObject prefabRoot = trans.gameObject;
|
||||
|
||||
Component[] components = prefabRoot.GetComponents<Component>();
|
||||
for (int i = 0; i < components.Length; i++)
|
||||
{
|
||||
var com = components[i];
|
||||
|
||||
if (com == null)
|
||||
continue;
|
||||
|
||||
MonoBehaviour monoCom = com as MonoBehaviour;
|
||||
if (monoCom == null)
|
||||
continue;
|
||||
Type monoType = monoCom.GetType();
|
||||
if (!monoType.Assembly.FullName.Contains("UnityEngine.UI"))
|
||||
continue;
|
||||
// 获取MonoScript资源
|
||||
MonoScript monoScript = MonoScript.FromMonoBehaviour(monoCom);
|
||||
if (monoScript != null)
|
||||
{
|
||||
// 获取MonoScript资源的GUID
|
||||
string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(monoScript));
|
||||
Debug.Log(nodename+" | <color=#FFF333>["+monoType.Name+"]</color> <color=#FF0000>"+guid+"</color><color=#00FF00>("+monoType.FullName+")</color>");
|
||||
ComType2GUID[monoType.FullName] =
|
||||
new AxiPrefabCache_Com2GUID()
|
||||
{
|
||||
SrcFullName = monoType.FullName,
|
||||
SrcName = monoType.Name,
|
||||
GUID = guid,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("!!!! 没得");
|
||||
}
|
||||
}
|
||||
|
||||
//遍历
|
||||
foreach (Transform child in trans.transform)
|
||||
LoopPrefabNode(nodename, child.gameObject, depth + 1);
|
||||
//#else
|
||||
// Debug.Log("低版本不要执行本函数");
|
||||
//#endif
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[2]生成中间脚本代码")]
|
||||
public static void Part2()
|
||||
{
|
||||
|
||||
#if UNITY_4_6
|
||||
if(System.IO.Directory.Exists(outCsDir))
|
||||
System.IO.Directory.Delete(outCsDir);
|
||||
#else
|
||||
if (UnityEngine.Windows.Directory.Exists(outCsDir))
|
||||
UnityEngine.Windows.Directory.Delete(outCsDir);
|
||||
#endif
|
||||
|
||||
|
||||
Directory.CreateDirectory(outCsDir);
|
||||
|
||||
|
||||
|
||||
#if UNITY_4_6
|
||||
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath(cachecfgPath,typeof(AxiPrefabCache)) as AxiPrefabCache;
|
||||
#else
|
||||
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath<AxiPrefabCache>(cachecfgPath);
|
||||
#endif
|
||||
foreach (var data in cache.caches)
|
||||
{
|
||||
string toName = "Axi" + data.SrcName;
|
||||
@ -160,12 +189,18 @@ public class AxiProjectTools : EditorWindow
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [2]生成中间脚本代码</color>");
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[3]收集生成的脚本")]
|
||||
public static void Part3()
|
||||
{
|
||||
#if UNITY_4_6
|
||||
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath(cachecfgPath,typeof(AxiPrefabCache)) as AxiPrefabCache;
|
||||
MonoScript[] allMonoScripts = (MonoScript[])Resources.FindObjectsOfTypeAll(typeof(MonoScript));
|
||||
#else
|
||||
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath<AxiPrefabCache>(cachecfgPath);
|
||||
List<MonoScript> allMonoScripts = FindAllAssetsOfType<MonoScript>();
|
||||
#endif
|
||||
|
||||
foreach (var data in cache.caches)
|
||||
{
|
||||
MonoScript monoScript = allMonoScripts.FirstOrDefault(w => w.name == data.ToName);
|
||||
@ -183,18 +218,23 @@ public class AxiProjectTools : EditorWindow
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [3]收集生成的脚本</color>");
|
||||
}
|
||||
|
||||
|
||||
static List<T> FindAllAssetsOfType<T>() where T : UnityEngine.Object
|
||||
{
|
||||
List<T> assets = new List<T>();
|
||||
|
||||
|
||||
string[] allGuids = AssetDatabase.FindAssets("");
|
||||
foreach (string guid in allGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.EndsWith(".cs") || path.EndsWith(".js") || path.EndsWith(".boo")) // Unity支持多种脚本语言,但现代Unity主要使用C#
|
||||
{
|
||||
#if UNITY_4_6
|
||||
T asset = AssetDatabase.LoadAssetAtPath(cachecfgPath,typeof(T)) as T;
|
||||
#else
|
||||
T asset = AssetDatabase.LoadAssetAtPath<T>(path);
|
||||
#endif
|
||||
|
||||
if (asset != null)
|
||||
{
|
||||
assets.Add(asset);
|
||||
@ -203,12 +243,18 @@ public class AxiProjectTools : EditorWindow
|
||||
}
|
||||
return assets;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[4]替换所有预制体和场景中的组件")]
|
||||
public static void Part4()
|
||||
{
|
||||
|
||||
#if UNITY_4_6
|
||||
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath(cachecfgPath,typeof(AxiPrefabCache)) as AxiPrefabCache;
|
||||
#else
|
||||
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath<AxiPrefabCache>(cachecfgPath);
|
||||
#endif
|
||||
|
||||
Dictionary<string, string> tempReplaceDict = new Dictionary<string, string>();
|
||||
foreach (var data in cache.caches)
|
||||
{
|
||||
@ -221,7 +267,7 @@ public class AxiProjectTools : EditorWindow
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [4]替换所有预制体和场景中的组件</color>");
|
||||
}
|
||||
|
||||
|
||||
static void ProcessAllPrefabs(string form, Dictionary<string, string> tempReplaceDict, bool reverse = false)
|
||||
{
|
||||
List<GameObject> prefabs = new List<GameObject>();
|
||||
@ -240,7 +286,7 @@ public class AxiProjectTools : EditorWindow
|
||||
}
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 替换值
|
||||
/// </summary>
|
||||
@ -257,17 +303,17 @@ public class AxiProjectTools : EditorWindow
|
||||
File.WriteAllLines(strFilePath, lines);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[5]UnPack所有嵌套预制体和场景中的预制体")]
|
||||
public static void UnpackPrefabs()
|
||||
{
|
||||
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
GoTAxiProjectToolsSence();
|
||||
string[] allAssetPaths = AssetDatabase.GetAllAssetPaths();
|
||||
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
GoTAxiProjectToolsSence();
|
||||
string[] allAssetPaths = AssetDatabase.GetAllAssetPaths();
|
||||
int prefabCount = 0;
|
||||
|
||||
|
||||
foreach (string path in allAssetPaths)
|
||||
{
|
||||
if (Path.GetExtension(path).Equals(".prefab"))
|
||||
@ -278,59 +324,59 @@ public class AxiProjectTools : EditorWindow
|
||||
}
|
||||
}
|
||||
Debug.Log($"{prefabCount}个预制体Unpack");
|
||||
|
||||
string[] sceneGuids = AssetDatabase.FindAssets("t:scene");
|
||||
foreach (string guid in sceneGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains(toolSenceName))
|
||||
continue;
|
||||
|
||||
EditorSceneManager.OpenScene(path);
|
||||
Scene currentScene = SceneManager.GetActiveScene();
|
||||
GameObject[] rootObjects = currentScene.GetRootGameObjects();
|
||||
|
||||
string[] sceneGuids = AssetDatabase.FindAssets("t:scene");
|
||||
foreach (string guid in sceneGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains(toolSenceName))
|
||||
continue;
|
||||
|
||||
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(path);
|
||||
UnityEngine.SceneManagement.Scene currentScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
|
||||
GameObject[] rootObjects = currentScene.GetRootGameObjects();
|
||||
foreach (GameObject rootObj in rootObjects)
|
||||
{
|
||||
// 遍历场景中的所有对象
|
||||
TraverseHierarchy(rootObj);
|
||||
}
|
||||
// Save the scene // 获取当前打开的场景
|
||||
currentScene = EditorSceneManager.GetActiveScene();
|
||||
// 保存场景到文件(默认路径和名称)
|
||||
bool success = EditorSceneManager.SaveScene(currentScene, currentScene.path);
|
||||
|
||||
Debug.Log($"{currentScene.name}场景中 所有物体Unpack");
|
||||
}
|
||||
|
||||
GoTAxiProjectToolsSence();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [5]UnPack所有预制体</color>");
|
||||
#else
|
||||
Debug.Log("低版本不要执行本函数");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void UnpackPrefab(string prefabPath)
|
||||
{
|
||||
// 遍历场景中的所有对象
|
||||
TraverseHierarchy(rootObj);
|
||||
}
|
||||
// Save the scene // 获取当前打开的场景
|
||||
currentScene = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene();
|
||||
// 保存场景到文件(默认路径和名称)
|
||||
bool success = UnityEditor.SceneManagement.EditorSceneManager.SaveScene(currentScene, currentScene.path);
|
||||
|
||||
Debug.Log($"{currentScene.name}场景中 所有物体Unpack");
|
||||
}
|
||||
|
||||
GoTAxiProjectToolsSence();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [5]UnPack所有预制体</color>");
|
||||
#else
|
||||
Debug.Log("低版本不要执行本函数");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void UnpackPrefab(string prefabPath)
|
||||
{
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
GameObject prefabInstance = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
||||
if (prefabInstance == null)
|
||||
{
|
||||
Debug.LogError($"Failed to load prefab at path: {prefabPath}");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var obj = GameObject.Instantiate(prefabInstance, null);
|
||||
TraverseHierarchy(obj);
|
||||
PrefabUtility.SaveAsPrefabAsset(obj, prefabPath);
|
||||
GameObject.DestroyImmediate(obj);
|
||||
#else
|
||||
#else
|
||||
Debug.Log("低版本不要执行本函数");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void TraverseHierarchy(GameObject obj)
|
||||
{
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
// 检查该对象是否是预制体的实例
|
||||
if (PrefabUtility.IsPartOfPrefabInstance(obj))
|
||||
{
|
||||
@ -338,80 +384,123 @@ public class AxiProjectTools : EditorWindow
|
||||
PrefabUtility.UnpackPrefabInstance(obj, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
|
||||
Debug.Log("Prefab instance converted to game object: " + obj.name);
|
||||
}
|
||||
|
||||
|
||||
// 递归遍历子对象
|
||||
for (int i = 0; i < obj.transform.childCount; i++)
|
||||
{
|
||||
TraverseHierarchy(obj.transform.GetChild(i).gameObject);
|
||||
}
|
||||
#else
|
||||
#else
|
||||
Debug.Log("低版本不要执行本函数");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[6]修复Sprite")]
|
||||
public static void FixMultipleMaterialSprites()
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:sprite");
|
||||
List<Sprite> spritesToFix = new List<Sprite>();
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[6]修复Sprite")]
|
||||
public static void FixMultipleMaterialSprites()
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:sprite");
|
||||
List<Sprite> spritesToFix = new List<Sprite>();
|
||||
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(path);
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(path);
|
||||
|
||||
// 检查是否有多个材质
|
||||
if (IsUsingMultipleMaterials(sprite))
|
||||
{
|
||||
spritesToFix.Add(sprite);
|
||||
Debug.Log("Found sprite with multiple materials: " + path);
|
||||
}
|
||||
}
|
||||
// 检查是否有多个材质
|
||||
if (IsUsingMultipleMaterials(sprite))
|
||||
{
|
||||
spritesToFix.Add(sprite);
|
||||
Debug.Log("Found sprite with multiple materials: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
// 修复每个找到的Sprite
|
||||
foreach (var sprite in spritesToFix)
|
||||
{
|
||||
FixSprite(sprite);
|
||||
}
|
||||
// 修复每个找到的Sprite
|
||||
foreach (var sprite in spritesToFix)
|
||||
{
|
||||
FixSprite(sprite);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [6]修复Sprite</color>");
|
||||
}
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [6]修复Sprite</color>");
|
||||
}
|
||||
|
||||
private static bool IsUsingMultipleMaterials(Sprite sprite)
|
||||
{
|
||||
if (sprite == null) return false;
|
||||
private static bool IsUsingMultipleMaterials(Sprite sprite)
|
||||
{
|
||||
if (sprite == null) return false;
|
||||
|
||||
// 获取精灵的材质
|
||||
var textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(sprite)) as TextureImporter;
|
||||
// 获取精灵的材质
|
||||
var textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(sprite)) as TextureImporter;
|
||||
|
||||
return textureImporter != null && textureImporter.spriteImportMode == SpriteImportMode.Multiple;
|
||||
}
|
||||
return textureImporter != null && textureImporter.spriteImportMode == SpriteImportMode.Multiple;
|
||||
}
|
||||
|
||||
private static void FixSprite(Sprite sprite)
|
||||
{
|
||||
// 获取Sprite的路径
|
||||
string path = AssetDatabase.GetAssetPath(sprite);
|
||||
var textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||
private static void FixSprite(Sprite sprite)
|
||||
{
|
||||
// 获取Sprite的路径
|
||||
string path = AssetDatabase.GetAssetPath(sprite);
|
||||
var textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||
|
||||
if (textureImporter != null)
|
||||
{
|
||||
// 保存当前切割信息
|
||||
SpriteMetaData[] originalMetaData = textureImporter.spritesheet;
|
||||
if (textureImporter != null)
|
||||
{
|
||||
// 保存当前切割信息
|
||||
SpriteMetaData[] originalMetaData = textureImporter.spritesheet;
|
||||
|
||||
// 临时禁用Sprite导入
|
||||
textureImporter.spriteImportMode = SpriteImportMode.None;
|
||||
textureImporter.SaveAndReimport();
|
||||
// 临时禁用Sprite导入
|
||||
textureImporter.spriteImportMode = SpriteImportMode.None;
|
||||
textureImporter.SaveAndReimport();
|
||||
|
||||
// 重新启用Sprite导入并保持原样切割参数
|
||||
textureImporter.spriteImportMode = SpriteImportMode.Multiple;
|
||||
textureImporter.spritesheet = originalMetaData; // 恢复原来的切割信息
|
||||
// 重新启用Sprite导入并保持原样切割参数
|
||||
textureImporter.spriteImportMode = SpriteImportMode.Multiple;
|
||||
textureImporter.spritesheet = originalMetaData; // 恢复原来的切割信息
|
||||
|
||||
// 重新导入以应用更改
|
||||
textureImporter.SaveAndReimport();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[7]导入后低版本执行:修复组件挂载预制体依赖丢失")]
|
||||
static void FixPrefabRefs()
|
||||
{
|
||||
// 1. 扫描所有预制体
|
||||
string[] prefabPaths = Directory.GetFiles("Assets", "*.prefab", SearchOption.AllDirectories);
|
||||
foreach (var path in prefabPaths) FixRefTypeInFile(path);
|
||||
|
||||
// 2. 处理场景文件
|
||||
string[] scenePaths = Directory.GetFiles("Assets", "*.unity", SearchOption.AllDirectories);
|
||||
foreach (var path in scenePaths) FixRefTypeInFile(path);
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [5]导入低版本后:修复预制体依赖丢失</color>");
|
||||
Debug.Log("修复完成!已处理" + prefabPaths.Length + "个预制体");
|
||||
}
|
||||
|
||||
public static void FixRefTypeInFile(string filePath)
|
||||
{
|
||||
string content = File.ReadAllText(filePath);
|
||||
// 匹配所有 {fileID: X, guid: Y, type: Z} 结构
|
||||
string pattern = @"(\{[^}]*guid:\s*(\w+)[^}]*type:\s*)3(\s*[^}]*\})";
|
||||
string newContent = Regex.Replace(content, pattern, match => {
|
||||
string guid = match.Groups[2].Value;
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
// 仅当资源类型为 GameObject 时修改 type
|
||||
if (AssetDatabase.GetMainAssetTypeAtPath(assetPath) == typeof(GameObject))
|
||||
// if (assetPath.ToLower().EndsWith(".prefab")
|
||||
////&& assetPath.Contains("/sound/")
|
||||
//&& assetPath.Contains("/level")
|
||||
// )
|
||||
{
|
||||
Debug.Log("已处理被引用项=>"+assetPath+" ,引用到=>"+ filePath);
|
||||
Debug.Log("原值=>" + match.Value + " ,处理值=>"+ match.Groups[1].Value + "2" + match.Groups[3].Value);
|
||||
//return match.Value;
|
||||
return match.Groups[1].Value + "2" + match.Groups[3].Value; // type:3→2
|
||||
}
|
||||
return match.Value;
|
||||
});
|
||||
File.WriteAllText(filePath, newContent);
|
||||
}
|
||||
|
||||
// 重新导入以应用更改
|
||||
textureImporter.SaveAndReimport();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,73 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
public class AxiStatisticsCache : ScriptableObject
|
||||
{
|
||||
public List<AxiStatisticsDatas> caches = new List<AxiStatisticsDatas>();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class AxiStatisticsDatas
|
||||
{
|
||||
/// <summary>
|
||||
/// [0]Sence [1]Prefab
|
||||
/// </summary>
|
||||
public int type;
|
||||
public string FullPath;
|
||||
public List<AxiStatistics_Node> nodes = new List<AxiStatistics_Node>();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class AxiStatistics_Node
|
||||
{
|
||||
public string Name;
|
||||
public List<AxiStatistics_Node_Link> link = new List<AxiStatistics_Node_Link>();
|
||||
public int LinkHash;
|
||||
public string LinkFullStr;
|
||||
//public string NodeFullPath;
|
||||
// /// <summary>
|
||||
// /// 表示相同路径只有一个
|
||||
// /// </summary>
|
||||
// public bool NodeIdxOnlyOne;
|
||||
/// <summary>
|
||||
/// 表示相同路径是第几个下标
|
||||
/// </summary>
|
||||
//public int NodeIdx;
|
||||
public List<AxiStatistics_Node_Component> components = new List<AxiStatistics_Node_Component>();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class AxiStatistics_Node_Link
|
||||
{
|
||||
public string Name;
|
||||
public bool OnlyOne;
|
||||
public int Idx;
|
||||
public int NodeHash;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class AxiStatistics_Node_Component
|
||||
{
|
||||
public string type;
|
||||
/// <summary>
|
||||
/// 表示相同组件只有一个
|
||||
/// </summary>
|
||||
public bool ComTypeOnlyOne;
|
||||
/// <summary>
|
||||
/// 表示相同组件是第几个下标
|
||||
/// </summary>
|
||||
public int ComIdxNum;
|
||||
//Rigboody
|
||||
public bool simulated;
|
||||
public float gravityScale;
|
||||
public bool isKinematic;
|
||||
//BoxCollider2D
|
||||
public Vector2 center;
|
||||
public Vector2 size;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4cee4feffb506b4c833262e779424f6
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
Loading…
Reference in New Issue
Block a user