1
\$\begingroup\$

I want to create an extension for the Unity 3D Editor and have an custom asset type. During the process of creation this I recognized that I would improve the UX/usability if I can specify the path where I want to create the asset by using right click. But I fail to get the context path of the right click and I cannot find any hints on google or at the unity scripting api. Below you can see an image of the process I tried to describe above.

Asset creation process

Here is the code that is responsible for handling the context creation "event".

[MenuItem("Assets/Create/Chat")]
public static void createChatViaMenu() {
    Chat c = Chatter.createDefaultChat();

    // This is the part where I want to insert the relative path.
    AssetDatabase.CreateAsset(c, "Assets/" + c.Title + ".asset");
}

If you need any more information please let me know.

\$\endgroup\$
0

3 Answers 3

2
\$\begingroup\$

You can get the path by using Selection.activeObject. Here is a small code to get this feature working :)

   string path = AssetDatabase.GetAssetPath (Selection.activeObject);

    if (path == "")
    {
        path = "Assets";
    }
    else if (Path.GetExtension(path) != "")
    {
        path = path.Replace(Path.GetFileName (AssetDatabase.GetAssetPath (Selection.activeObject)), "");
    }
    AssetDatabase.CreateAsset (asset, AssetDatabase.GenerateUniqueAssetPath (path + "/New MyAsset.asset"));
\$\endgroup\$
1
  • \$\begingroup\$ A couple of caveats: 1. You may want to use Path.HasExtension() 2. You may want to reuse path var instead of calling again to AssetDatabase. 3. Checking the extension does not guarantee that activeObject is a folder. You might have a file without extension. A better approach would be using FileAttributes. 4. AFAIK, Selection.activeObject always returns the last asset file you have clicked on, never a folder. \$\endgroup\$ Commented Mar 20, 2020 at 9:40
1
\$\begingroup\$

Use built-in property

If your asset is simple and doesn't need special treatment, you should use built-in property to generate a "create asset" menu.

[CreateAssetMenu( menuName = "Wappen Asset/WaveBankData" )]
public class WaveBankData : ScriptableObject
{

And it will magically added to right click menu -> Create. Has same functionality as Unity's one. It will be created in current browser location, prompt for a rename, etc.

enter image description here


Via MenuItem callback

If you really want to use customized MenuItem. Here is how TextMesh pro determine current right-click folder. If you call Selection.assetGUIDs under MenuItem callback, it will guarantee current displaying folder (the one that you clicked on its empty space)

For full script, see your own \Packages\com.unity.textmeshpro\Scripts\Editor\TMP_ColorGradientAssetMenu.cs

    [MenuItem("Assets/Create/TextMeshPro/Color Gradient", false, 115)]
    public static void CreateColorGradient(MenuCommand context)
    {
        string filePath;

        if (Selection.assetGUIDs.Length == 0)
            filePath = "Assets/New TMP Color Gradient.asset";
        else
            filePath = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]);

(BONUS) The TRUE Project browser current directory

Is hidden inside internal unity ProjectWindowUtil.TryGetActiveFolderPath static function and needs reflector to access it. If you are coder wiz and really want to have it, here it is. (For non coder, I wont explain this, please do C# research on your own)

enter image description here

using UnityEngine;
using UnityEditor;
using System.Reflection;

    // Define this function somewhere in your editor class to make a shortcut to said hidden function
    private static bool TryGetActiveFolderPath( out string path )
    {
        var _tryGetActiveFolderPath = typeof(ProjectWindowUtil).GetMethod( "TryGetActiveFolderPath", BindingFlags.Static | BindingFlags.NonPublic );

        object[] args = new object[] { null };
        bool found = (bool)_tryGetActiveFolderPath.Invoke( null, args );
        path = (string)args[0];

        return found;
    }

Note: tested in Unity 2019.4.19f

\$\endgroup\$
0
\$\begingroup\$

AFAIK, using AssetDatabase.GetAssetPath with Selection never returns a folder, instead of that always returns the last asset file you have clicked on (the one being shown in the inspector). Here is my try, in case you needed full path (but it would be easy to modify it to return a relative path):

private static string GetClickedDirFullPath()
{
    string clickedAssetGuid = Selection.assetGUIDs[0];
    string clickedPath      = AssetDatabase.GUIDToAssetPath(clickedAssetGuid);
    string clickedPathFull  = Path.Combine(Directory.GetCurrentDirectory(), clickedPath);

    FileAttributes attr = File.GetAttributes(clickedPathFull);
    return attr.HasFlag(FileAttributes.Directory) ? clickedPathFull : Path.GetDirectoryName(clickedPathFull);
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .