UnityEditor 編輯器間快速復(fù)制粘貼

經(jīng)常需要從Assets面板復(fù)制文件,每次都要 右鍵 - Show in Exlorer ,然后復(fù)制,巨麻煩。寫了個工具,直接右鍵Asset面板在Unity不同項目間快速復(fù)制粘貼,或者直接復(fù)制到剪切板。

主要分成兩種,一種是從一個編輯器到另外一個編輯器拷貝,一種是想拷貝到系統(tǒng)剪切板。

menu

從編輯器到剪切板

Unity編輯器里沒辦法像C# Winform 一樣直接向系統(tǒng)剪切板添加文件夾,只能復(fù)制文本,但是PowerShell可以,在UnityEditor里又可以執(zhí)行Powershell。所以通過執(zhí)行PowerShell來向系統(tǒng)剪切板加入要復(fù)制的文件列表。powershell使用剪切板 見 官方文檔 。

執(zhí)行powershell

public static bool RunCommand(string command)
{
    using (Process process = new Process())
    {
        process.StartInfo.FileName = "powershell";
        process.StartInfo.Arguments = command;
        process.StartInfo.CreateNoWindow = true; // 不顯示窗口
        process.StartInfo.ErrorDialog = true;
        process.StartInfo.UseShellExecute = false;
        try
        {
            process.Start();
            process.WaitForExit();
            process.Close();
        }
        catch (Exception e)
        {
            Debug.LogError(e);
            return false;
        }
    }
    return true;
}

然后加入Assets菜單,獲取選中的目錄拼接一串命令運行即可。

[MenuItem("Assets/復(fù)制 - 剪切板復(fù)制", false, 21)]
private static void CopyToClipboard()
{
    StringBuilder stringBuilder = new StringBuilder("Set-Clipboard -Path ");
    for (int i = 0; i < Selection.assetGUIDs.Length; i++)
    {
        string path = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[i]);
        if (i != 0) stringBuilder.Append(",");
        stringBuilder.Append("\"");
        stringBuilder.Append(AssetPath2FullPath(path));
        stringBuilder.Append("\"");
    }
    RunCommand(stringBuilder.Replace("/", "\\").ToString());
}

注意事項:Assets路徑需要轉(zhuǎn)換成絕對路徑。這樣粘貼時才有效。

從編輯器到編輯器

雖然可以通過powershell可以加入文件列表到剪切板, 但是沒發(fā)現(xiàn)通過powershell粘貼,這邊比較坑爹。不過可以通過代碼獲取到復(fù)制的文本:

GUIUtility.systemCopyBuffer

所以采取的辦法是,如果在編輯器間復(fù)制,把文件列表路徑,存起來序列化后復(fù)制到文本,然后粘貼時讀取系統(tǒng)的剪切板 然后解析下路徑列表,再通過C#執(zhí)行復(fù)制粘貼擦操作。

此外,有時需要通過導(dǎo)出導(dǎo)入包來復(fù)制,以便識別到依賴。道理相同,在一邊導(dǎo)出,把列表文本寫到剪切板。

直接復(fù)制

[MenuItem("Assets/復(fù)制 - 編輯器復(fù)制", false, 21)]
private static void CopyToEditor()
{
    ClipItem item = new ClipItem(ContentType.File);
    foreach (var guiD in Selection.assetGUIDs)
    {
        string path = AssetDatabase.GUIDToAssetPath(guiD);
        item.Values.Add(AssetPath2FullPath(path));
    }
    CopyClipboardItem(item);
    Debug.Log("已復(fù)制" + Selection.assetGUIDs.Length + "條數(shù)據(jù),可在其他 Unity 編輯器里粘貼!");
}

序列化并復(fù)制文本

public static void CopyClipboardItem(ClipItem item)
{
    BinaryFormatter formatter = new BinaryFormatter();
    using (MemoryStream stream = new MemoryStream())
    {
        formatter.Serialize(stream, item);
        TextEditor te = new TextEditor {text = Convert.ToBase64String(stream.ToArray())};
        te.OnFocus();
        te.Copy();
    }
}

通過導(dǎo)包

和上面唯一的區(qū)別就是導(dǎo)出一個包到臨時目錄存起來

[MenuItem("Assets/復(fù)制 - 導(dǎo)出包復(fù)制", false, 21)]
private static void CopyAsPackage()
{
    string[] assetPaths = new string[Selection.assetGUIDs.Length];
    for (int i = 0; i < Selection.assetGUIDs.Length; i++)
    {
        assetPaths[i] = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[i]);
    }
    string outPath = Path.Combine(Application.temporaryCachePath,
        Random.Range(0, 1024) + ".unitypackage");
    AssetDatabase.ExportPackage(assetPaths, outPath,
        ExportPackageOptions.Recurse | ExportPackageOptions.IncludeDependencies);
    ClipItem item = new ClipItem(ContentType.Package);
    item.Values.Add(outPath);
    CopyClipboardItem(item);
}

粘貼

[MenuItem("Assets/粘貼", false, 21)]
private static void Paste()
{
    ClipItem item;
    try
    {
        byte[] bytes = Convert.FromBase64String(GUIUtility.systemCopyBuffer);
        BinaryFormatter formatter = new BinaryFormatter();
        using (MemoryStream stream = new MemoryStream(bytes))
        {
            item = formatter.Deserialize(stream) as ClipItem;
        }
    }
    catch (FormatException e)
    {
        throw new FormatException("沒有從剪切板解析到有效的數(shù)據(jù)!");
    }
    string assetPath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);
    switch (item.Type)
    {
        case ContentType.File:
            CopyListFileInEditor(item.Values, AssetPath2FullPath(assetPath));
            break;
        case ContentType.Package:
            if (item.Values.Count > 0 && Path.GetExtension(item.Values[0]).Equals(".unitypackage"))
                Package2Folder.ImportPackageToFolder(item.Values[0], assetPath, true);
            break;
        default:
            break;
    }
}


public static void CopyListFileInEditor(List<string> sourcePaths, string targetPath)
{
    bool isAuto = EditorPrefs.GetBool(KeyAutoRefresh, true);
    if (isAuto) EditorPrefs.SetBool(KeyAutoRefresh, false);
    foreach (var path in sourcePaths)
    {
        string destName = Path.Combine(targetPath, Path.GetFileName(path));
        if (File.Exists(path))
        {
            File.Copy(path, destName);
        }
        else
        {
            CopyDir(path, destName);
        }
    }
    if (isAuto) EditorPrefs.SetBool(KeyAutoRefresh, true);
    AssetDatabase.Refresh();
}

public static void CopyDir(string sourcePath, string destinationPath)
{
    DirectoryInfo info = new DirectoryInfo(sourcePath);
    if (!Directory.Exists(destinationPath))
        Directory.CreateDirectory(destinationPath);
    foreach (FileSystemInfo fsi in info.GetFileSystemInfos())
    {
        string destName = Path.Combine(destinationPath, fsi.Name);

        if (fsi is FileInfo)
        {
            File.Copy(fsi.FullName, destName);
        }
        else
        {
            Directory.CreateDirectory(destName);
            CopyDir(fsi.FullName, destName);
        }
    }
}

需要注意的是,在編輯器里直接通過腳本粘貼之前,需要禁用掉Unity的自動刷新,否則可能沒復(fù)制完線程便中斷了。Unity設(shè)置里的自動刷新配置保存在 EditorPrefs,Key:kAutoRefresh。


以上的代碼并不完整,另外還有一些細節(jié),比如導(dǎo)入包時 可以導(dǎo)入指定Assets目錄等一些細節(jié)上的沒貼出來。代碼在這里 QuickCopy.cs ,直接放到項目中Editor文件夾下就能用。

無關(guān)緊要的部分

從一個項目復(fù)制到另一個項目,都得需要上面的代碼,意味著每次都得先拷貝下這個代碼才行,也相當麻煩??梢宰龀赡K化,這樣自己電腦上隨便打開一個項目不用復(fù)制代碼也能用了。參見之前的博客:UnityEditor Unity的模塊

為了方便自己,打包了一份。在這里 UnityQuickCopyModule.dll ,把該文件放到任意Unity項目,用管理員權(quán)限啟動Unity,菜單欄安裝即可,然后就可以全局通用了。

menu2

以上所有腳本和文件 https://github.com/liangddyy/UnityClipboard

博客原文 https://539go.com/2018/02/04/Unity-QuickCopy/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容