解决各种漏传 资源 / 代码 的疑难杂症.
因为Unity比较特殊的meta文件系统, 忘传漏传文件在后期可能导致重大引用丢失, 将SVN整合进项目势在必行. TortoiseSVN自带了命令行工具, 安装的时候选择了的话就能用了
直接代码:
using UnityEngine; using UnityEditor; using System.Diagnostics; using System.Collections.Generic; namespace MyEditor { public class UnitySVN { private const string Add_CMD = "add"; private const string COMMIT_CMD = "commit"; private const string UPDATE_CMD = "update"; private const string REVERT_CMD = "revert"; private static System.Text.StringBuilder ms_sb = new System.Text.StringBuilder(); #region MenuItem Funcs [MenuItem("Assets/SVN/Update", false, 1001)] public static void SVN_Update() { var paths = GetAssetPathList(); if(paths.Count > 0) { Update(paths: paths.ToArray()); } } [MenuItem("Assets/SVN/Revert", false, 1002)] public static void SVN_Revert() { var paths = GetAssetPathList(); if(paths.Count > 0) { Revert(paths.ToArray()); } } [MenuItem("Assets/SVN/Commit", false, 1003)] public static void SVN_Commit() { var paths = GetAssetPathList(); if(paths.Count > 0) { Commit("UnitySVN Upload", true, paths.ToArray()); } } #endregion #region Wrapped Funcs // add public static void Add(params string[] paths) { WrappedCommadn(Add_CMD, paths, false); } // update public static void Update(params string[] paths) { WrappedCommadn(UPDATE_CMD, paths, false); SaveAndRefresh(); } // revert public static void Revert(params string[] paths) { WrappedCommadn(REVERT_CMD, paths, false); SaveAndRefresh(); } // add->update->commit public static void Commit(string log, bool add = true, params string[] paths) { if(add) { Add(paths); } Update(paths); string extMsg = log ?? string.Empty; WrappedCommadn(command: COMMIT_CMD, paths: paths, newThread: true, extCommand: "/logmsg:\"Auto Upload : " + (extMsg) + "\""); } ////// Wrap SVN Command /// /// /// /// public static void WrappedCommadn(string command, string[] paths, bool newThread = false, string extCommand = null) { if(paths == null || paths.Length == 0) { return; } ms_sb.Append(paths[0]); for(int i = 1; i < paths.Length; i++) { ms_sb.Append("*"); ms_sb.Append(paths[i]); } string cmd = "/c tortoiseproc.exe /command:{0} /path:\"{1}\" {2} /closeonend 2"; string pathString = ms_sb.ToString(); var commandString = string.Format(cmd, command, pathString, extCommand ?? string.Empty); ProcessStartInfo info = new ProcessStartInfo("cmd.exe", commandString); info.WindowStyle = ProcessWindowStyle.Hidden; if(newThread) { System.Threading.ThreadPool.QueueUserWorkItem((_obj) => { RunProcess(info); }); } else { RunProcess(info); } } #endregion #region Help Funcs public static HashSetGetAssets() { HashSet allAssets = new HashSet (); const string BaseFolder = "Assets"; foreach(var obj in Selection.objects) { var assetPath = AssetDatabase.GetAssetPath(obj); List fullDirs = FullDirectories(assetPath, BaseFolder); allAssets.UnionWith(fullDirs); var dps = AssetDatabase.GetDependencies(assetPath, true); foreach(var dp in dps) { if(dp != assetPath) { List dpsDirs = FullDirectories(dp, BaseFolder); allAssets.UnionWith(dpsDirs); } } } return allAssets; } public static List GetAssetPathList() { var path = new List (GetAssets()); path.Sort((_l, _r) => { if(_l.Length > _r.Length) { return 1; } if(_l.Length < _r.Length) { return -1; } return 0; }); return path; } public static void SaveAndRefresh() { AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } public static List FullDirectories(string path, string baseFolder) { List retVal = new List (); retVal.Add(path); retVal.Add(path + ".meta"); baseFolder = baseFolder.Replace("\\", "/"); var dir = System.IO.Path.GetDirectoryName(path).Replace("\\", "/"); while(string.IsNullOrEmpty(dir) == false && dir != baseFolder) { retVal.Add(dir); retVal.Add(dir + ".meta"); dir = System.IO.Path.GetDirectoryName(dir).Replace("\\", "/"); } return retVal; } private static void RunProcess(ProcessStartInfo info) { Process p = null; try { using(p = Process.Start(info)) { p.WaitForExit(); } } catch(System.Exception ex) { UnityEngine.Debug.LogError(@ex.ToString()); if(p != null) { p.Kill(); } } } #endregion } /* / closeonend:0不自动关闭对话框 / closeonend:1会自动关闭,如果没有错误 / closeonend:2会自动关闭,如果没有发生错误和冲突 / closeonend:3会自动关闭,如果没有错误,冲突和合并 / closeonend:4会自动关闭,如果没有错误,冲突和合并 */ }
主要的功能还是自动上传功能, 被选中物体的所有关联引用都会被加入上传列表, 并且所有文件夹也会被加入, 这样就保证了Add逻辑不会错误.