Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Glurth · Jul 12, 2017 at 04:41 PM · editormaterialsassetspathbuilt-in

GetAssetPath returning incomplete path for default materials

I have an editor script in which I’m attempting to get the path of a user selected material. While the following code works fine for user created materials, but if the user happens to select a built-in material, the function does not return the full path of the material. (It looks like it’s just returning the folder.)

 Material defaultMat = (Material)AssetDatabase.LoadAssetAtPath(matPath, typeof(Material));
 Material newdefaultMat = (Material)EditorGUILayout.ObjectField(defaultEdgeRendererMaterialGUID.label, defaultMat, typeof(Material), false);
 matPath = AssetDatabase.GetAssetPath(newdefaultMat);
 if (defaultMat != newdefaultMat)
     Debug.Log("new mat path: "+matPath);

Log Output:

 new mat path: Resources/unity_builtin_extra

Question: Given the material selected by the user, how can I get its path, in all cases?

Other details: I’m trying to store the user selected material as a string, of some form, so that I can store it in an EditorPreference. Then I can load and reference this material later, possibly even in a different session, as a default Material when creating custom objects. Workarounds to achieve this are welcome answers as well.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Bunny83 · Jul 12, 2017 at 05:31 PM

As you might know you can pack multiple assets into a single "asset file". That is the case here. The individual assets do not have seperate asset files. The actual asset file is located here:

 C:\Program Files\Unity\Editor\Data\Resources\unity_builtin_extra

It contains many assets. If you need to find one particular asset you have to use a method like AssetDatabase.LoadAllAssetsAtPath and find your desired asset. Keep in mind that all UnityEngine.Objects can have a "name". Though not all internal assets have one.

edit

Here's an example script which allows you to get a list of all assets stored in the unity_builtin_extra asset file:

 //BuiltInAssetsExtra.cs
 using UnityEngine;
 
 public class BuiltInAssetsExtra : MonoBehaviour
 {
     public UnityEngine.Object[] objs;
     [ContextMenu("GetAllExtraAssets")]
     void GetAllExtraAssets()
     {
 #if UNITY_EDITOR
         objs = UnityEditor.AssetDatabase.LoadAllAssetsAtPath("Resources/unity_builtin_extra");
 #endif
     }
 }

Attach it to an object and execute the method from the context menu.

second edit

I haven't really tested this, but it probably should work:

 //AssetDatabaseHelper.cs
 using UnityEditor;
 using System.Linq;

 public class AssetDatabaseHelper
 {
     public static T LoadAssetFromUniqueAssetPath<T>(string aAssetPath) where T : UnityEngine.Object
     {
         if (aAssetPath.Contains("::"))
         {
             string[] parts = aAssetPath.Split(new string[] { "::" },System.StringSplitOptions.RemoveEmptyEntries);
             aAssetPath = parts[0];
             if (parts.Length > 1)
             {
                 string assetName = parts[1];
                 System.Type t = typeof(T);
                 var assets = AssetDatabase.LoadAllAssetsAtPath(aAssetPath)
                     .Where(i => t.IsAssignableFrom(i.GetType())).Cast<T>();
                 var obj = assets.Where(i => i.name == assetName).FirstOrDefault();
                 if (obj == null)
                 {
                     int id;
                     if (int.TryParse(parts[1], out id))
                         obj = assets.Where(i => i.GetInstanceID() == id).FirstOrDefault();
                 }
                 if (obj != null)
                     return obj;
             }
         }
         return AssetDatabase.LoadAssetAtPath<T>(aAssetPath);
     }
     public static string GetUniqueAssetPath(UnityEngine.Object aObj)
     {
         string path = AssetDatabase.GetAssetPath(aObj);
         if (!string.IsNullOrEmpty(aObj.name))
             path += "::" + aObj.name;
         else
             path += "::" + aObj.GetInstanceID();
         return path;
     }
 }

This allows you to create a unique "assetpath" which includes the actual asset name or instance ID after a double colon "::". The "LoadAssetFromUniqueAssetPath" method will then do the reverse. The type check should allow inheritance. So LoadAssetFromUniqueAssetPath<Object>(somePath) will work with any type (in case you don't know the type at compile time).

Again, not tested yet.

Ok i quickly tested both methods and it works with the built-in "Default-Material". It gives you a path like this:

 "Resources/unity_builtin_extra::Default-Material"

Which does create a proper reference to the Default-Material. I also works with an actual assetpath. If you use GetUniqueAssetPath on a prefab reference you get this:

 "Assets/MyPrefab.prefab::MyPrefab"

"LoadAllAssetsAtPath" also works on single assets.

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Glurth · Jul 12, 2017 at 05:45 PM 0
Share

So how do I reference a $$anonymous$$aterial stored like this, using a string? Looks like: Store its name/GUID seperately along with the path.
Then check if GetAssetAtPath returns null, if so use LoadAllAssetsAtPath to load everything at that path, then search through all those loaded assets for the one with the stored name/GUID.

Yuk, is there a better way?

avatar image Bunny83 Glurth · Jul 12, 2017 at 05:57 PM 0
Share

Yes, that's probably the only way. You can't get a direct assetpath to an asset that is inside an "assetpackage".

I'm not sure if that would work across multiple sessions, but you could try storing the instance ID of the object in question and use EditorUtility.InstanceIDToObject.

avatar image Bunny83 · Jul 12, 2017 at 06:59 PM 0
Share

ps: choosing the right type might be necessary. For example the assetpath:

  "Resources/unity_builtin_extra::Checkmark"

still refers to two assets. The first is a Texture2D, the second is a Sprite that references the texture. So using the proper type might be necessary in some cases.

avatar image Glurth · Jul 13, 2017 at 12:35 AM 0
Share

Good gosh Bunny, you just saved me hours! I have confirmed it works in my project too (also only tested for mats, so far) , it fit right in seamlessly (just added if (!aObj) return ""; to GetUniqueAssetPath)!
Edit/Update: Tests confirm this also works for built-in meshes!

 builtinCube$$anonymous$$esh=AssetDatabaseHelper.LoadAssetFromUniqueAssetPath< $$anonymous$$esh > ( "Library/unity default resources::Cube");

This string was generated by simply passing the builtin cube mesh to the GetUniqueAssetPath function, and displaying the output.

avatar image atkins79 · Dec 10, 2020 at 03:22 PM 0
Share

Did this stop working in more recent Unity versions? UnityEditor.AssetDatabase.LoadAllAssetsAtPath("Resources/unity_builtin_extra"); comes back empty for me in 2018.3.

avatar image atkins79 atkins79 · Dec 10, 2020 at 03:24 PM 0
Share

Oh, yes, it was a regression in Unity 2018.3, fixed in 2019.1: https://issuetracker.unity3d.com/issues/using-loadallassetsatpath-to-load-the-paths-does-not-load-objects-stored-at-paths-and-leaves-the-the-expecting-object-empty

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

89 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Material doesn't have a texture property '_MainTex' 8 Answers

Pressing play Causes Re-instancing of material (Editor) 1 Answer

Bezier curve that update in real time. 1 Answer

Editor crash on all scenes and projects 1 Answer

Why Are My Project Assets Constantly Re-Importing? 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges