Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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
6
Question by Tomer-Barkan · Jul 06, 2013 at 09:15 AM · texturematerialbugrenderer

Modifying material modifies the actual .mat file!

Ok, I've encountered some very weird behavior, and wondering if it's designed like this or a bug, and if anyone has ideas of workarounds.

I'm trying to change the texture of a material, that will affect all the renderers that use this material. What I did, was assign the Material property of my script through the editor

 public Material someMat;

And then within the game I use:

 someMat.mainTexture = otherTexture;

Now, everything is fine, the new material is used, and then I stop the game. Lo and behold, in the editor, after stopping the game, I still see all the renderers using the updated material! When I check in my file system, I see that the script actually changed the .mat file, not just for runtime, but permanently.

Is this the planned behavior or a bug? I thought only editor scripts modify actual resource files. Can anyone suggest a way to do this other than going through all the renderers and modifying them one by one?

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
11
Best Answer

Answer by Bunny83 · Jul 06, 2013 at 09:50 AM

When you create a Material in your project it will be an asset saved to the .mat file. This asset can be used on as much renderers as you like. All those renderers will use the material as sharedMaterial. That means all renderers just reference the material you assigned to them which is in your case the material asset inside your project folder.

Accessing the .material property in game will create a duplicate of the used material only for this renderer. This actually disconnects the renderer from the shared material.

What might confuses you is the fact that changes to the material are preserved when you leave playmode. That's because only things that are saved to the scene is reverted when leaving playmode. Unity saves the scene to disk when you enter playmode and restore it afterwards. All assets you reference directly are changed directly. This is also true for prefab-assets. Just try it. Create a prefab of a cube, reference the prefab in a script of yours and change the position of the prefab. When you leave playmode you will notice that the prefab will have the new position you've just set in-game.

That's why you should avoid changing assets directly. In a built game that's not a real problem since all assets are stored in your build and loaded into memory when the game starts. Changes to assets will be lost once you restart your game.

However in the editor you can change any asset at any time. The only difference between editor scripts and ingame script is that editor scripts have an additional API set (the UnityEditor namespace) which is only available inside the editor. In general all script can do the same thing since they all run in the same mono environment. In-game script could also use editor stuff, but they are compiled without the UnityEditor reference so all the stuff in there is not known at compile time. Also it wouldn't make sense to do something like that since you can't build your game when you use UnityEditor stuff.

Ok back to the topic: What you can do is find all renderers which are using the material in question, create a duplicate in memory and assign this duplicated Material to all renderers sharedMaterial property.

Something like that:

 // C#
 public Material matAsset;
 
 void Start()
 {
     var allRenderers = (Renderer[])FindObjectsOfType(typeof(Renderer));
     var matInstance = new Material(matAsset);
     foreach (Renderer R in allRenderers)
         if (R.sharedMaterial == matAsset)
             R.sharedMaterial = matInstance;
 }

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 Tomer-Barkan · Jul 07, 2013 at 05:43 AM 1
Share

Thank you, very informative and helpful. In my solution, I'm setting the default texture at the beginning of the game. Do you expect any performance hits?

I still think it's weird, even more now that you tell me that you'll get different behavior in editor than actual player...

avatar image scvn8010 · Oct 18, 2014 at 04:31 PM 0
Share

How can I edit mat file directly ? I google many tool but I don't find any tool which can edit mat file

avatar image RobAtApex · Jul 18, 2018 at 01:26 AM 0
Share

Is this a wise thing to do in builds, or only in the Editor? If it doesn't help in builds, then would it be better not to do this, as it just uses more resources? Would it be better to do this:

 #if UNITY_EDITOR
     $$anonymous$$aterial mat = new $$anonymous$$aterial(matAsset);
 #else
     $$anonymous$$aterial mat = matAsset;
 #endif

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

21 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

Related Questions

Changing two different objects renderer colour 1 Answer

How to switch the texture being used by the material of the mesh renderer 1 Answer

How to change a value in custom shader through script, C# 1 Answer

How could I make the texture on one object follow the rotation of another object? 0 Answers

Standard material shader ignoring SetFloat property "_Mode"? 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