Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 11 Next capture
2021 2022 2023
1 capture
11 Jun 22 - 11 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 /
This question was closed Jun 15, 2018 at 08:52 AM by Harinezumi for the following reason:

The question is answered, right answer was accepted

avatar image
2
Question by Harinezumi · Jul 20, 2015 at 12:33 PM · scripting problemmaterials

Directly assigning Material through Renderer.materials doesn't work

Hi there,

I'm trying to assign materials to a game object through C# script. It all works fine when I assign through Renderer.material, even if the game object has multiple Renderers on it (I get all Renderers in all child objects). However, when the Renderer has multiple materials, iterating through and assigning through Renderer.materials does not change the materials!

Here's the code I'm using (renderers is an array of the Renderers on the game object):

 public void SetMaterials(Material newMaterial) {
     for(int i = 0; i < renderers.Length; ++i) { 
         // renderers[i].material = newMaterial; <-- THIS WORKS, BUT ONLY SETS THE FIRST MATERIAL!
         Material[] materials = renderers[i].materials;
         for (int j = 0; j < materials.Length; ++j) {
             materials[j] = newMaterial; <-- THIS DOES NOT AFFECT THE MATERIALS
         }
     }
 }

Does someone have an idea what the problem is?

Thanks a lot in advance! :)

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

2 Replies

  • Sort: 
avatar image
11
Best Answer

Answer by Harinezumi · Jul 20, 2015 at 11:38 AM

OK, so I actually realised what the problem was while writing the question, but I wanted to post it anyway so that if someone else runs into it, they can find the solution :)

You cannot assign a Material to a Renderer directly through Renderer.materials[i], you have to create a separate array of Materials, assign the wanted values to that, and then set that array for Renderer.materials. Like this:

 public void SetMaterials(Material newMaterial) {
     for(int i = 0; i < renderers.Length; ++i) { 
         Material[] materials = new Material[renderers[i].materials.Length]; // <-- CREATING THE TEMPORARY ARRAY
         for (int j = 0; j < materials.Length; ++j) {
             materials[j] = newMaterial; 
         }
         renderers[i].materials = materials; // <-- ASSIGNING THE WHOLE ARRAY
     }
 }

The reason is that Renderer.materials does not directly access the array of materials in the Renderer, it returns a temporary copy of the array, so whatever you assign to that will be in vain (it is good for reading info though). This might seem unintuitive, but from a programming point of view is the right thing to do.

I hope this helps others! :)

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 ssurget · Nov 24, 2015 at 04:59 PM 1
Share

I encountered the exact same issue and your post gave the answer :).

Thanks to you, I won't loose any time (nor hair)!

avatar image TooManySugar · Sep 28, 2017 at 10:40 PM 0
Share

TX, I was getting kinda mad with this XD

avatar image ArcticPinou · Mar 23, 2018 at 09:04 PM 0
Share

Huge thank you !

avatar image
1

Answer by Danor · Jul 11, 2017 at 03:08 PM

First of all thanks to Harinezum for the original! My issue was that i needed specific materials changed and some unchanged, so i made this variation and leaving it here for anyone who needs this.

(You have to add (Instance) to the name or it won't work)

   public Material newMat; // is the newMaterial
     private Material keepMat;
     public Renderer[] renderers;
 
     public void SetMaterials(Material newMaterial)
     {
         for (int i = 0; i < renderers.Length; ++i)
         {
             Material[] materials = new Material[renderers[i].materials.Length]; // <-- CREATING THE TEMPORARY ARRAY
             for (int j = 0; j < materials.Length; ++j)
             {
                 if (renderers[i].materials[j].name == "DontChangeYourMat (Instance)") {
                     oldMat = renderers[i].materials[j];
                     materials[j] = oldMat;
                 } 
                else if (renderers[i].materials[j].name == "YourMaterialName(Instance)") materials[j] = newMaterial; 
                  /* add more else if's for more mats or use a switch if you need to change tons of them */
             }
             renderers[i].materials = materials; // <-- ASSIGNING THE WHOLE ARRAY
         }
     }











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

Follow this Question

Answers Answers and Comments

7 People are following this question.

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

Related Questions

How to change material that is being scrolled for Material.SetTextureOffset 2 Answers

Scripted SetTextureOffset not working after switching to Universal Render Pipeline 1 Answer

textures/Materials Disappearing Upon Play 0 Answers

Changing a material source 1 Answer

Modify skybox material property in-game via script 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