Search Unity

how to get currently selected folder for putting new Asset into?

Discussion in 'Scripting' started by teatime, Mar 10, 2011.

  1. teatime

    teatime

    Joined:
    Jun 16, 2008
    Posts:
    129
    When you create an asset in the Project tab, the default/built-in assets are created inside whatever folder is selected or was last selected in the Project tab. It's probably there but I'm not finding how to replicate this in the documentation. In other words, right now I have
    Code (csharp):
    1. AssetDatabase.CreateAsset(asset,
    2. AssetDatabase.GenerateUniqueAssetPath("Assets/New MyAsset.asset"));
    Is there any way to do something like
    Code (csharp):
    1. AssetDatabase.CreateAsset(asset,
    2. AssetDatabase.GenerateUniqueAssetPath(SomeElusiveClass.TheCurrentlySelectedAssetFolderPath + "New Myasset.asset"));
    ?
     
  2. teatime

    teatime

    Joined:
    Jun 16, 2008
    Posts:
    129
    bump?
     
  3. steamrollerstudios

    steamrollerstudios

    Joined:
    Apr 19, 2009
    Posts:
    60
    Is this what your looking for?

    EditorUtility.GetAssetPath(Selection.activeObject)
     
    Zahlen and rakkarage like this.
  4. teatime

    teatime

    Joined:
    Jun 16, 2008
    Posts:
    129
    thanks for the heads up. it takes a little more work to get the behavior right for all cases, the following code seems to be working great:
    Code (csharp):
    1. string path = AssetDatabase.GetAssetPath (Selection.activeObject);
    2. if (path == "")
    3. {
    4.     path = "Assets";
    5. }
    6. else if (Path.GetExtension(path) != "")
    7. {
    8.     path = path.Replace(Path.GetFileName (AssetDatabase.GetAssetPath (Selection.activeObject)), "");
    9. }
    10. AssetDatabase.CreateAsset (asset, AssetDatabase.GenerateUniqueAssetPath (path + "/New MyAsset.asset"));
    11.        
    you'll also have to include the System.IO namespace.
     
    Last edited: Mar 22, 2011
    yonixw likes this.
  5. sebas77

    sebas77

    Joined:
    Nov 4, 2011
    Posts:
    1,644
    great I needed it and it worked smoothly
     
  6. yoyo

    yoyo

    Joined:
    Apr 16, 2010
    Posts:
    112
    This will do the same thing, but is a little simpler and doesn't rely on files having extensions and directories not having them:

    Code (csharp):
    1.         string path = "Assets";
    2.         foreach (UnityEngine.Object obj in Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets))
    3.         {
    4.             path = AssetDatabase.GetAssetPath(obj);
    5.             if (File.Exists(path))
    6.             {
    7.                 path = Path.GetDirectoryName(path);
    8.             }
    9.             break;
    10.         }
    11.  
     
    yonixw, madpoly, baerbel and 4 others like this.
  7. JvetS

    JvetS

    Joined:
    Mar 20, 2013
    Posts:
    1
    I found the following implementation to work quite good as well. https://gist.github.com/JvetS/5208916
    I had some issues with the proposed solution, but I didn't bother to debug further and came up with this solution.

    Might break somewhere down the road though due to it being private.
     
    nicloay likes this.
  8. Matthew A

    Matthew A

    Joined:
    Nov 24, 2010
    Posts:
    15
    Thanks for posting that JvetS, it's really useful.

    Path.GetDirectoryName() in yoyo's reply doesn't seem to work because it normalizes the path ("Assets/" -> "assets/", which may be fine for the Windows, but I guess Unity is case sensitive).
     
  9. Regis-Ramillien

    Regis-Ramillien

    Joined:
    Apr 16, 2013
    Posts:
    1
    A small comment for those who are reading this thread.
    Yoyo's solution was the best for me.
    While other solutions are not selecting folder or are complicated, the Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets) select both folders or objects and is simple to use.
     
  10. fibriZo-raZiel

    fibriZo-raZiel

    Joined:
    Sep 18, 2013
    Posts:
    1
    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):

    Code (CSharp):
    1. private static string GetClickedDirFullPath()
    2. {
    3.     string clickedAssetGuid = Selection.assetGUIDs[0];
    4.     string clickedPath          = AssetDatabase.GUIDToAssetPath(clickedAssetGuid);
    5.     string clickedPathFull     = Path.Combine(Directory.GetCurrentDirectory(), clickedPath);
    6.  
    7.     FileAttributes attr = File.GetAttributes(clickedPathFull);
    8.     return attr.HasFlag(FileAttributes.Directory) ? clickedPathFull : Path.GetDirectoryName(clickedPathFull);
    9. }
     
    _geo__ and aidangig56 like this.
  11. SolidAlloy

    SolidAlloy

    Joined:
    Oct 21, 2019
    Posts:
    58
    If you want to create an asset just like it is done in the Project window, then
    ProjectWindowUtil.CreateAsset()
    is the right way to do it. It will start the asset creation and prompt the user to input an asset name. A default asset name is passed as an argument and shows up as a suggestion to the user.

    If you don't want the user to be able to rename the asset, it can only be done through Reflection. The methods described above use Selection in different ways, but if the currently open folder is empty, none of them will work because no asset will be selected in the Project window.

    Code (CSharp):
    1. MethodInfo getActiveFolderPath = typeof(ProjectWindowUtil).GetMethod(
    2.     "GetActiveFolderPath",
    3.     BindingFlags.Static | BindingFlags.NonPublic);
    4.  
    5. string folderPath = (string) getActiveFolderPath.Invoke(null, null);
     
    Last edited: Jan 22, 2021
  12. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    And this is why no-one should post off-site links in forums :(. (it's 404, deleted, gone, vanished).

    (which reminds me of this XKCD:
     
    _geo__ and PrimalCoder like this.
  13. SolidAlloy

    SolidAlloy

    Joined:
    Oct 21, 2019
    Posts:
    58
    [Off-topic, sorry]

    I like to create a GitHub gist for a snippet if it is bigger than a couple of lines. The issue here is not posting a third-party link but the fact that the user decided to remove a gist that they posted on a forum (this is evil, never do this). When a snippet is posted on the forum, there are multiple replies like "I fixed this", "I made it work in the new Unity version", etc., and each user posts a copy of the snippet with only one or two different lines. On the other hand, a gist can be updated, and you will always find the latest version at the link without scrolling through a long thread of snippets.
     
  14. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    For Unity forums, the multiple replies with small changes actually works great, better than a gist. Most of the time it's more useful to see all the different versions, and respond to different individual people about what THEY changed and why.

    For other platforms/languages/types of problem a gist can work better, but in Unity usually everyone's doing slghtly different things. AND Uinty keeps breaking stuff between versions - so you often NEED to see the old version, not the new version (which is possible with a gist, but a lot more effport than simply seeing it directly in the thread).
     
  15. GuidewireGames

    GuidewireGames

    Joined:
    Apr 20, 2017
    Posts:
    27
    It seems that
    AssetDatabase.GetAssetPath
    provides a path when selecting a folder in right view of the Project panel, but not from the hierarchical list on the left.

    I guess I need to look into the ProjectWindowUtil
     
  16. Thygrrr

    Thygrrr

    Joined:
    Sep 23, 2013
    Posts:
    700
    Here's mine. Doesn't use reflection, just available public API.
    Ironically, that function is just a few lines below the one that other person grabbed with reflection.

    Code (CSharp):
    1. var asset = ScriptableObject.CreateInstance<MyAssetType>();
    2.  
    3. const string fileName = "Unnamed Asset.asset";
    4. ProjectWindowUtil.CreateAsset(asset, fileName);