Bulk Save Selected Dependent Objects in Editor

Here’s an Editor script to save all selected items in the Project window.

I needed it because often I browse through compilation projects and I want to export a single scene’s elements into a unitypackage for reference later. This script makes it pretty easy to select all related assets ready for export.

  • Add this script to an Editor folder in your project
  • In the Project window, rightclick on the scene object
  • Choose “Select dependencies”. All used assets used in the scene will get selected.
  • In the Unity main menu, choose “Edit” > “Bulk Copy…”
  • The Bulk Copy window will open and list the selected objects
  • Hit the “Copy” button and browse to the folder you want to copy the objects to – or create a new folder. Note, all files will be copied to this target folder without their parent folders.
  • To Export the scene or object family to a unitypackage, open a blank project and drag/drop the folder containing the copied assets into the Project window.
  • Rightclick on the folder in the Project window and choose “Export Package”. Tick “Include Dependencies”.
  • Save the unitpackage. From now on you can import this unitypackage into any project and it will recreate the folder and have all required assets available.

This isn’t polished code. It works for me – YMMV. I’m sure it could be automated further. Use at your own risk. Windows only.

/* v1.0 170603
* For exporting packages.
* For any scene in the editor window, rightclick and choose "select dependencies"
* Now, with all dependent objects selected, go to Main Menu > Edit > Bulk Copy...
* Items to copy will be listed. Hit the "Copy" button and choose target folder.
* All items will be copied to that folder.
*/
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
using System.Text;

public class BulkCopyAssets : ScriptableWizard
{

    static private string targetPath = @"C:\Temp";
    static private List<string> objectPaths;

    [MenuItem("Edit/Bulk Copy...")]
    static void CreateWizard()
    {
        ScriptableWizard.DisplayWizard("Bulk Copy Assets", typeof(BulkCopyAssets), "Copy");
    }

    void OnEnable()
    {
        UpdateSelectionHelper();
    }

    void OnSelectionChange()
    {
        UpdateSelectionHelper();
    }

    void UpdateSelectionHelper()
    {
        helpString = (Selection.objects != null) ?
            string.Concat(
                "Number of objects selected: " + Selection.objects.Length + System.Environment.NewLine
                , GetObjNamesString(Selection.objects)
            )
            : "";
        objectPaths = GetObjNamesArray(Selection.objects);
    }

    List<string> GetObjNamesArray(Object[] selectionObjects)
    {
        string assetBasePath = Application.dataPath;
        string fixedPath, assetPath;
        List<string> result = new List<string>();

        for (int i = 0; i < selectionObjects.Length; i++)
        {
            assetPath = AssetDatabase.GetAssetPath(selectionObjects[i]);
            fixedPath = string.Concat(
                    assetBasePath
                    , @"\"
                    , assetPath.Remove(
                        0
                        , 7
                    )
                ).Replace(@"/", @"\");

            result.Add(fixedPath);
            Debug.Log(result[i]);
        }
        return result;
    }

    string GetObjNamesString(Object[] selectionObjects)
    {
        List<string> result = new List<string>();
        for (int i = 0; i < selectionObjects.Length; i++) result.Add(selectionObjects[i].name);
        return string.Join(System.Environment.NewLine, result.ToArray());
    }

    void OnWizardCreate()
    {

        if (Selection.objects == null)
            return;

        targetPath = EditorUtility.OpenFolderPanel(
            "Target Path"
            , ""
            , ""
        ).Replace(@"/", @"\");

        if (string.IsNullOrEmpty(targetPath) || !Directory.Exists(targetPath)) return;
        Debug.Log("Targetpath = " + targetPath);

        for (int i = 0; i < objectPaths.Count; i++)
        {
            if ((File.GetAttributes(objectPaths[i]) & FileAttributes.Directory) != FileAttributes.Directory)
            {
                string sourceFile, targetFile;

                sourceFile = objectPaths[i];
                targetFile = Path.Combine(
                    targetPath
                    , Path.GetFileName(objectPaths[i])
                );

                // copy main file
                File.Copy(
                    sourceFile
                    , targetFile
                    , true
                );

                // and the .meta file
                File.Copy(
                    string.Concat(sourceFile, ".meta")
                    , string.Concat(targetFile, ".meta")
                    , true
                );
            }
        }
    }
}
1 Like

@Fergicide This code is pure gold.
It needs a few tweeks but It was exactly what I was looking for.

Glad to hear it was useful!

I’ve been using Godot for some years now, but nice to get a ping from my old Unity days :slight_smile: