Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 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 kebrus · Oct 19, 2012 at 02:55 PM · materialinstanceleaksharedmaterial

how do i create material instances without errors

Is is possible to create an instance of a material within the editor? sometimes i get "New Material (Instance)" just by playing around with it, i wanted to know if i can actually do it on purpose, i would like to create a single material apply it to a bunch of objects and then change some properties individually without having to create a new material

i also want to know how to do the exact same thing with scripts without getting the leak error, basically so far I've been creating instances of a material by simply running a renderer.material to force the instance, but then i get the leak errors, what is the trick to not leak, i know that line only runs once but that doesn't stop unity to error out

Comment
Add comment · Show 2
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 cregox · Nov 26, 2012 at 06:12 PM 0
Share

Did you ever solve this?

avatar image kebrus · Nov 26, 2012 at 08:26 PM 0
Share

no i didn't :( and i still want to know how to do this

4 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by DaveA · Oct 19, 2012 at 08:04 PM

The trick is to set sharedMaterial, rather than Material.

Example of how to create material here: http://docs.unity3d.com/Documentation/ScriptReference/AssetDatabase.CreateAsset.html

Comment
Add comment · Show 1 · 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 kebrus · Oct 19, 2012 at 08:52 PM 1
Share

maybe i didn't explain it well, shared$$anonymous$$aterial would be ok if i wanted to keep only one material for multiple objects, but i actually want to instantiate the material, my two problems is that i want to be able to do it on the editor AND/BUT with editor scripts i get an error of leaking materials

Instantiating material due to calling renderer.material during edit mode. This will leak materials into the scene. You most likely want to use renderer.shared$$anonymous$$aterial ins$$anonymous$$d.

avatar image
2

Answer by Kurdle_4855 · Mar 05, 2016 at 04:11 PM

I know this thread is old, but here's a little piece of code for those who find this thread looking for the same answers I did. Create a C# script, call it MaterialInstancer, and place it in a folder called 'Editor' then copy and paste this code: using UnityEngine; using System.Collections; using UnityEditor;

 public class MaterialInstancer : Editor {
 
     [MenuItem("GameObject/Instance Material")]
     public static void Instance()
     {
         if(Selection.activeGameObject == null || Selection.activeGameObject.GetComponent<MeshRenderer>() == null){
             Debug.LogError("No Valid Object Selected");
             return;
         }
         
         Material mat = Selection.activeGameObject.GetComponent<MeshRenderer>().sharedMaterial;
         Selection.activeGameObject.GetComponent<MeshRenderer>().sharedMaterial = new Material(mat);
 
     }
 
 }

All you need to do is select a gameobject in the scene with a meshrenderer, and go to 'GameObject/Instance Material'. This will create an instance of the material on the selected gameobject, and allow you to edit it without changing any of the other materials.

Comment
Add comment · Show 1 · 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 jampakdd · Oct 04, 2020 at 12:11 AM 0
Share

Awesome! Still works unity 2020 :)

avatar image
1

Answer by SinPin · Dec 06, 2012 at 03:13 AM

Hey ;)

I had the same problem as you did - Just tried out some things to use different materials / colors for objects, I created with an editor script... I constantly ran into this "Leak-Error".

Now I just found a solution that worked for me (in Unity4) without getting this leak error, but with having the benefit of using different colors for different objects with sharedMaterial.

I have quickly written a short demo:

 using UnityEngine;
 using UnityEditor;
 using System.Collections;
 
 public class MyEditorScript : Editor 
 {
     // If I want to have new Objects with different colors:
     [MenuItem("Test/Create Object with Material")]
     public static void CreateDemoObjects()
     {
         // Create a new GameObject with a material...
         GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
         obj.name = "TestObject";
         // Important: sharedMaterial, not material.
         obj.renderer.sharedMaterial = new Material(Shader.Find("Diffuse")); // REF1
         obj.renderer.sharedMaterial.color = Color.green;
         
         GameObject obj2 = GameObject.CreatePrimitive(PrimitiveType.Sphere);
         obj2.name = "TestObject2";
         obj2.transform.position = new Vector3(2f, 0f, 0f);
         obj2.renderer.sharedMaterial.color = Color.red;
     }
     
 // If I just want to change the material, you might use the color of an existing Object
 //    public void JustASnippet()
 //    {
 //        // GameObject _target -&gt; Your exiting target object...
 //        Material mat;
 //        // Still using sharedMaterial:
 //        mat = new Material(_target.renderer.sharedMaterial);
 //        mat.color = Color.blue; // Taking blue color for demo...
 //        
 //        // Work with "mat" here...
 //        // e.g.: obj.renderer.sharedMaterial = mat;
 //    }
 }

Just try it out in an empty scene -> Drop this Script in an "Editor" Directory. Then activate it by Menu: Test->"Create Object with Material".

As you can see, I am creating new objects and change their color (you can play around with this to change the whole material or whatever you need) without using the material propertie.

Find the "// REF1" comment -> If you comment this line out, you will get two red objects, so this line actually did the trick. (I get a green cube and a red sphere.)

I don't know why, but this "Leak-Error" is always called when using (even reading) the "material" property. (It is not called for creating a "new Material()")

There is only one problem with this code, I have figured out for now: After creating the two demo objects, all the next objects, you will create (Menu: GameObject->Create Other->Cube) in this scene are red by default. (sharedMaterial was set to red at the end of the CreateDemoObjects() Function.)

Also take a look at the JustASnippet() Function, where are some lines, that worked for me too. (I created a new Material based on the sharedMaterial of an already existing object.) This Function-Code is not complete, but I think you can see what I mean.

Just to mention it: If you don't want to create a new Material via Script, you can create it in the Editor and use this one...

I hope my code helped you to avoid the "Leak-Error". If I figure out more about this topic, I will update my content.

Yours SinPin

Comment
Add comment · Show 3 · 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 AlucardJay · Dec 06, 2012 at 03:13 AM 0
Share

Yes, please format your code. You can do this by highlighting all your code, then clicking the 10101 button at the top of the edit window.

Though, it may be easier just to delete the code, paste it in again from the source, then highlight all the code and press the 101010 button at the top of the edit window before posting. When you don't mark your code as code, the text gets html escaped and it gets really hard to reformat it.

avatar image AlucardJay · Dec 06, 2012 at 03:15 AM 0
Share

I formatted the code, please check it is correct.

avatar image SinPin · Dec 06, 2012 at 09:42 AM 0
Share

@alucardj: I reposted and formated the code - Thanks for your help :)

avatar image
1

Answer by Clemens-Scharfen · Feb 20, 2020 at 01:27 PM

Hi there,

I am aware that this thread is old, but I came here to look for a solution and was not completely happy with the provided answers (although I wrote one of them myself with another account 8 years ago :P ). I liked the answer from @Kurdle_4855, but I had the impression, that the material instance was gone when restarting the editor. To avoid the "leaking material" issue and to work with instanciated prefabs, I came up with my own (second) solution, that I wanted to share with you (or myself in the future :D ).

Basicly, the code does not really instanciate the material, but creates a copy from the original material, that can be shared via .sharedMaterial property without changing the appearence of other elements.

 using UnityEditor;
 using UnityEngine;
 
 public class MaterialInstancer : Editor
 {
     // This function creats a new material based on the one, that is referenced to the selected object(s) and saves this new material into a sub directory close to the original material.
     // Note: If you want to change a prefab, instanciate the prefab in a scene, use the InstanceMaterial for alle materials that you want to create an material-instance, and apply the prefab changes to the prefab.
     // If you do changes to a prefab directly in the prefab editor, the changes will be lost as soon as the prefab-editor is closed.
     [MenuItem("GameObject/Create Material Instance", false, 1111)]
     public static void InstanceMaterial()
     {
         foreach(Transform selectedTrans in Selection.transforms)
         {
             if (selectedTrans != null)
             {
                 MeshRenderer selectedMeshRenderer = selectedTrans.GetComponent<MeshRenderer>();
                 if(selectedMeshRenderer != null)
                 {
                     Material selectedMat = selectedMeshRenderer.sharedMaterial;
                     if(selectedMat != null)
                     {
                         // Create Material:
                         Material materialInstance = new Material(selectedMat);
 
                         // Save material to assets:
                         string parentDir = AssetDatabase.GetAssetPath(selectedMat); // returns something like Assets/Materials/matName.mat
                         parentDir = parentDir.Substring(0, parentDir.Length - (selectedMat.name.Length + ".mat".Length + 1)); // Results in Assets/Materials
                         string instanceFolder = selectedMat.name + "Instances";
                         string saveMatInstancePath = parentDir + "/" + instanceFolder;
                         if(AssetDatabase.IsValidFolder(saveMatInstancePath) == false)
                         {
                             string guid = AssetDatabase.CreateFolder(parentDir, instanceFolder);
                             string newFolderPath = AssetDatabase.GUIDToAssetPath(guid);
                             Debug.Log("[Create Material Instance] Created new directory for instanced material: " + newFolderPath);
                         }
 
                         // In case, material already exists, add number to its name:
                         string assetName = selectedMat.name + "Instance";
                         string[] searchPaths = new string[] { saveMatInstancePath };
                         int count = 0;
                         while(AssetDatabase.FindAssets(assetName, searchPaths).Length > 0)
                         {
                             assetName = selectedMat.name + "Instance" + (++count).ToString();
                         }
 
                         // Save asset:
                         AssetDatabase.CreateAsset(materialInstance, saveMatInstancePath + "/" + assetName + ".mat");
 
                         // Link material to game object:
                         selectedMeshRenderer.sharedMaterial = materialInstance;
 
                         Debug.Log("[Create Material Instance] " + selectedTrans.name + "s material got instantiated successfully.", selectedTrans.gameObject);
                     }
                     else
                     {
                         Debug.LogWarning("[Create Material Instance] Selected element does not have a material that can be instanciated.", selectedTrans.gameObject);
                     }
                 }
                 else
                 {
                     Debug.LogWarning("[Create Material Instance] Selected Element does not have a MeshRenderer.", selectedTrans.gameObject);
                 }
             }
             else
             {
                 Debug.LogWarning("[Create Material Instance] Something went wrong, the selected gameObject does not exist.");
             }
         }
     }
 
     [MenuItem("GameObject/Create Material Instance", true)]
     public static bool CheckInstanceMaterial()
     {
         return (Selection.transforms != null && Selection.transforms.Length > 0);
     }
 }
Comment
Add comment · 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

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

16 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

Related Questions

Finding and replacing all "instanced" materials 2 Answers

sharedMaterial not working after instantiate 0 Answers

Fade 2 out of 3 gameobjects on the screen who have the same material 2 Answers

When generating prefab, i cant load images from either resource or assetbundle 2 Answers

Two questions about building particle systems from scripts 1 Answer


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