好久没更新博客了,博客主题和一些样式也都改了,可能没有之前的好看,但是内容是不变的。博客的服务器也换成Linux的服务器了,之前Windows的服务器老是崩溃,Linux的就稳定多了。
别的就不多说了,今天要更新的工具是很早之前就写好的,只是没有更新,还有好多新的东西也都没来得及写出来呢,搞得我都不知道从哪个开始写了。这个文章要介绍的是复制文件夹,并且重新生成依赖关系,这个是一个可能经常会用到的功能。以为之前项目有好多东西需要复用,就需要复制一个,但是复制之后预制体上的图片和音频等还是复制之前的文件依赖关系,所以就有了现在的这个工具类。废话不多说,下面上代码。文章源自大腿Plus-https://www.zhaoshijun.com/archives/1623
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
using System; using System.Collections.Generic; using System.IO; using UnityEditor; using UnityEngine; public class CopyFolderKeepAssetsUsingEditor { [MenuItem("Assets/复制文件夹(复制依赖关系) %#D", false, 0)] static public void CopyFolderKeepAssetsUsing() { string oldFolderPath = AssetDatabase.GetAssetPath(Selection.objects[0]); string[] s = oldFolderPath.Split('/'); string folderName = s[s.Length - 1]; if (folderName.Contains(".")) { Debug.LogError("该索引不是文件夹名字"); return; } string copyedFolderPath = Path.GetFullPath(".") + Path.DirectorySeparatorChar + oldFolderPath; string tempFolderPath = Application.dataPath.Replace("Assets", "TempAssets") + SplitStr(oldFolderPath) + "_Copy"; string newFoldrPath = tempFolderPath.Replace("TempAssets", "Assets"); CopyDirectory(copyedFolderPath, tempFolderPath); //重新生成guids RegenerateGuids(copyedFolderPath); CopyDirectory(copyedFolderPath, newFoldrPath); AssetDatabase.DeleteAsset(oldFolderPath); CopyDirectory(tempFolderPath, copyedFolderPath); AssetDatabase.Refresh(); AssetDatabase.SaveAssets(); } private static string SplitStr(string path) { string str = ""; for (int i = 0; i < path.Split('/').Length; i++) { if (i != 0) { string _str = "/" + path.Split('/')[i]; str += _str; } } return str; } #region Copy public static void CopyDirectory(string sourceDirectory, string destDirectory) { //判断源目录和目标目录是否存在,如果不存在,则创建一个目录 if (!Directory.Exists(sourceDirectory)) { Directory.CreateDirectory(sourceDirectory); } if (!Directory.Exists(destDirectory)) { Directory.CreateDirectory(destDirectory); } //拷贝文件 CopyFile(sourceDirectory, destDirectory); //拷贝子目录 //获取所有子目录名称 string[] directionName = Directory.GetDirectories(sourceDirectory); foreach (string directionPath in directionName) { //根据每个子目录名称生成对应的目标子目录名称 string directionPathTemp = Path.Combine(destDirectory, directionPath.Substring(sourceDirectory.Length + 1));// destDirectory + "\\" + directionPath.Substring(sourceDirectory.Length + 1); //递归下去 CopyDirectory(directionPath, directionPathTemp); } } public static void CopyFile(string sourceDirectory, string destDirectory) { //获取所有文件名称 string[] fileName = Directory.GetFiles(sourceDirectory); foreach (string filePath in fileName) { //根据每个文件名称生成对应的目标文件名称 string filePathTemp = Path.Combine(destDirectory, filePath.Substring(sourceDirectory.Length + 1));// destDirectory + "\\" + filePath.Substring(sourceDirectory.Length + 1); //若不存在,直接复制文件;若存在,覆盖复制 if (File.Exists(filePathTemp)) { File.Copy(filePath, filePathTemp, true); } else { File.Copy(filePath, filePathTemp); } } } #endregion #region GUID private static readonly string[] kDefaultFileExtensions = { // "*.meta", // "*.mat", // "*.anim", // "*.prefab", // "*.unity", // "*.asset" "*.*" }; static public void RegenerateGuids(string _assetsPath, string[] regeneratedExtensions = null) { if (regeneratedExtensions == null) { regeneratedExtensions = kDefaultFileExtensions; } // Get list of working files List<string> filesPaths = new List<string>(); foreach (string extension in regeneratedExtensions) { filesPaths.AddRange( Directory.GetFiles(_assetsPath, extension, SearchOption.AllDirectories) ); } // Create dictionary to hold old-to-new GUID map Dictionary<string, string> guidOldToNewMap = new Dictionary<string, string>(); Dictionary<string, List<string>> guidsInFileMap = new Dictionary<string, List<string>>(); // We must only replace GUIDs for Resources present in Assets. // Otherwise built-in resources (shader, meshes etc) get overwritten. HashSet<string> ownGuids = new HashSet<string>(); // Traverse all files, remember which GUIDs are in which files and generate new GUIDs int counter = 0; foreach (string filePath in filesPaths) { EditorUtility.DisplayProgressBar("Scanning Assets folder", MakeRelativePath(_assetsPath, filePath), counter / (float)filesPaths.Count); string contents = string.Empty; try { contents = File.ReadAllText(filePath); } catch (Exception e) { Debug.LogError(filePath); Debug.LogError(e.ToString()); counter++; continue; } IEnumerable<string> guids = GetGuids(contents); bool isFirstGuid = true; foreach (string oldGuid in guids) { // First GUID in .meta file is always the GUID of the asset itself if (isFirstGuid && Path.GetExtension(filePath) == ".meta") { ownGuids.Add(oldGuid); isFirstGuid = false; } // Generate and save new GUID if we haven't added it before if (!guidOldToNewMap.ContainsKey(oldGuid)) { string newGuid = Guid.NewGuid().ToString("N"); guidOldToNewMap.Add(oldGuid, newGuid); } if (!guidsInFileMap.ContainsKey(filePath)) guidsInFileMap[filePath] = new List<string>(); if (!guidsInFileMap[filePath].Contains(oldGuid)) { guidsInFileMap[filePath].Add(oldGuid); } } counter++; } // Traverse the files again and replace the old GUIDs counter = -1; int guidsInFileMapKeysCount = guidsInFileMap.Keys.Count; foreach (string filePath in guidsInFileMap.Keys) { EditorUtility.DisplayProgressBar("Regenerating GUIDs", MakeRelativePath(_assetsPath, filePath), counter / (float)guidsInFileMapKeysCount); counter++; string contents = File.ReadAllText(filePath); foreach (string oldGuid in guidsInFileMap[filePath]) { if (!ownGuids.Contains(oldGuid)) continue; string newGuid = guidOldToNewMap[oldGuid]; if (string.IsNullOrEmpty(newGuid)) throw new NullReferenceException("newGuid == null"); contents = contents.Replace("guid: " + oldGuid, "guid: " + newGuid); } //File.WriteAllText(filePath, contents); FileManager.CreateFile(filePath, System.Text.Encoding.UTF8.GetBytes(contents)); } EditorUtility.ClearProgressBar(); } private static IEnumerable<string> GetGuids(string text) { const string guidStart = "guid: "; const int guidLength = 32; int textLength = text.Length; int guidStartLength = guidStart.Length; List<string> guids = new List<string>(); int index = 0; while (index + guidStartLength + guidLength < textLength) { index = text.IndexOf(guidStart, index, StringComparison.Ordinal); if (index == -1) break; index += guidStartLength; string guid = text.Substring(index, guidLength); index += guidLength; if (IsGuid(guid)) { guids.Add(guid); } } return guids; } private static bool IsGuid(string text) { for (int i = 0; i < text.Length; i++) { char c = text[i]; if ( !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')) ) return false; } return true; } private static string MakeRelativePath(string fromPath, string toPath) { Uri fromUri = new Uri(fromPath); Uri toUri = new Uri(toPath); Uri relativeUri = fromUri.MakeRelativeUri(toUri); string relativePath = Uri.UnescapeDataString(relativeUri.ToString()); return relativePath; } #endregion } |
具体的原理就是复制完之后重新生成GUID,然后重新生成依赖关系。这里我还做了文件备份,具体备份在项目根目录的Assets同级目录下的TempAssets文件夹下。具体使用方法是选中要复制的文件夹,右键第一个选项或者使用快捷键Ctrl+Shift+D完成复制文章源自大腿Plus-https://www.zhaoshijun.com/archives/1623 文章源自大腿Plus-https://www.zhaoshijun.com/archives/1623
我的微信
微信扫一扫

shijun_z
我的QQ
QQ扫一扫

846207670
评论