How to dynamically set a random Material on a GameObject











up vote
4
down vote

favorite
1












I'm a total newcomer to unity and I was just wondering how to set a material from C#?



I have a prefab model and I can change the texture from the editor no problem. What I want to do is randomly set the material when an instance of the prefab is generated.



Here is the field I want to change:



Unity Field



And I am creating these with the following code:



Instantiate(eggPrefab, spawnPos, Quaternion.identity);


(Where eggPrefab is a public Transform).



I hope that is enough information!



Thank you.










share|improve this question




























    up vote
    4
    down vote

    favorite
    1












    I'm a total newcomer to unity and I was just wondering how to set a material from C#?



    I have a prefab model and I can change the texture from the editor no problem. What I want to do is randomly set the material when an instance of the prefab is generated.



    Here is the field I want to change:



    Unity Field



    And I am creating these with the following code:



    Instantiate(eggPrefab, spawnPos, Quaternion.identity);


    (Where eggPrefab is a public Transform).



    I hope that is enough information!



    Thank you.










    share|improve this question


























      up vote
      4
      down vote

      favorite
      1









      up vote
      4
      down vote

      favorite
      1






      1





      I'm a total newcomer to unity and I was just wondering how to set a material from C#?



      I have a prefab model and I can change the texture from the editor no problem. What I want to do is randomly set the material when an instance of the prefab is generated.



      Here is the field I want to change:



      Unity Field



      And I am creating these with the following code:



      Instantiate(eggPrefab, spawnPos, Quaternion.identity);


      (Where eggPrefab is a public Transform).



      I hope that is enough information!



      Thank you.










      share|improve this question















      I'm a total newcomer to unity and I was just wondering how to set a material from C#?



      I have a prefab model and I can change the texture from the editor no problem. What I want to do is randomly set the material when an instance of the prefab is generated.



      Here is the field I want to change:



      Unity Field



      And I am creating these with the following code:



      Instantiate(eggPrefab, spawnPos, Quaternion.identity);


      (Where eggPrefab is a public Transform).



      I hope that is enough information!



      Thank you.







      c# unity3d






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 21 at 22:11









      Programmer

      75k1080142




      75k1080142










      asked Nov 21 at 21:01









      ls_dev

      9610




      9610
























          3 Answers
          3






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          I think mixing the random material behaviour with creation behaviour is overcomplicating things. Just create a component that randomises a GameObject's material on Start and it will run when you instantiate your prefab.



          public class MaterialRandomiser : MonoBehaviour {

          [SerializeField]
          private Material _materials;
          [SerializeField]
          private Renderer _renderer;

          public void Start () {
          ChangeMaterial();
          }

          public void Reset () {
          _renderer = GetComponent<Renderer>();
          }

          public void ChangeMaterial () {
          _renderer.material = SelectRandomMaterial();
          }

          private Material SelectRandomMaterial () {
          return _materials[Random.Range(0, _materials.Length)];
          }

          }


          Attach it to your prefab and now when you spawn them, they will have random materials. You now also have the option to use the same code on non-prefab objects as well. Just don't forget to assign the materials!






          share|improve this answer























          • This was actually super easy to add without changing any of my existing code. Thank you!
            – ls_dev
            Nov 23 at 14:54


















          up vote
          5
          down vote













          After you instantiate the GameObject, get the MeshRenderer from it then change it's material:



          public GameObject eggPrefab;
          public Vector3 spawnPos;
          public Material mat;

          void Start()
          {
          GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
          obj.GetComponent<MeshRenderer>().material = mat;
          }


          If you don't have the material then you can create one with a shader and assign it to the MeshRenderer:



          GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);

          //Find the Standard Shader
          Material mat = new Material(Shader.Find("Standard"));
          //Set Texture on the material
          //mat.SetTexture("_MainTex", yourTexture);

          obj.GetComponent<MeshRenderer>().material = mat;




          Finally, if you have more than one material then use the materials property instead of the material property and assign your array of material to it:



          GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);

          //Find the Standard Shader
          Material mat = new Material(Shader.Find("Standard"));
          //Set Texture on the material
          //mat.SetTexture("_MainTex", yourTexture);

          //Create array of mats (Create one for example)
          Material mats = new Material[1];
          mats[0] = mat;

          obj.GetComponent<MeshRenderer>().materials = mats;


          Edit:



          I missed the random part. If you want random material selection, just use Random.Range to select one item from the array of Material.



          public GameObject eggPrefab;
          public Vector3 spawnPos;
          public Material mats;

          void Start()
          {
          GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
          int matIndex = UnityEngine.Random.Range(0, mats.Length);
          obj.GetComponent<MeshRenderer>().material = mats[matIndex];
          }





          share|improve this answer























          • @ls_dev Every time you assign to Renderer.material you're (somehow) assigning a new instance of your material and increasing your number of draw calls. Always use Renderer.sharedMaterial to avoid this.
            – Kevin Remo
            Nov 21 at 21:44






          • 1




            @KevinRemo No. Not every time. It happens once only for each call on the renderer. Aslo, there are times when you need Renderer.material then Renderer.sharedMaterial. It totally depends on what OP is doing because if you have many objects/prefabs referencing one material, Renderer.material should be used to change their individual colors. If you want to change all the color of objects using that material, use Renderer.sharedMaterial. OP may use MaterialBlock to prevent creating new instances but it breaks batching.
            – Programmer
            Nov 21 at 21:51












          • Thank you for the help, I will try this tomorrow and update the thread.
            – ls_dev
            Nov 21 at 22:12






          • 1




            @ls_dev It should be noted that Renderer.material automatically clones materials when its first invoked. Its one of those "does things to be easy on the developer" helper functionalities.
            – Draco18s
            Nov 22 at 4:30


















          up vote
          1
          down vote













          You could do the following using an materials array.



              public Material materialsArray;
          public GameObject prefab;
          private Vector3 pos = new Vector3(0, 0, 0);
          private Quaternion rot = Quaternion.identity;

          private void Start()
          {
          Material mat = RandomMaterial(materialsArray);
          InstantiateWithMaterial(prefab, pos, rot, mat);
          }

          public Material RandomMaterial(Material _array_)
          {
          return _array_[Random.Range(0, _array_.Length)];
          }

          public void InstantiateWithMaterial(GameObject _prefab_, Vector3 _pos_, Quaternion _rot_, Material _mat_)
          {
          GameObject obj_ = Instantiate(_prefab_, _pos_, _rot_);
          obj_.gameObject.GetComponent<MeshRenderer>().material = _mat_;
          }


          This should work how you want, just place on an empty GameObject and populate the materials array with all the materials you want.






          share|improve this answer





















            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53420416%2fhow-to-dynamically-set-a-random-material-on-a-gameobject%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote



            accepted










            I think mixing the random material behaviour with creation behaviour is overcomplicating things. Just create a component that randomises a GameObject's material on Start and it will run when you instantiate your prefab.



            public class MaterialRandomiser : MonoBehaviour {

            [SerializeField]
            private Material _materials;
            [SerializeField]
            private Renderer _renderer;

            public void Start () {
            ChangeMaterial();
            }

            public void Reset () {
            _renderer = GetComponent<Renderer>();
            }

            public void ChangeMaterial () {
            _renderer.material = SelectRandomMaterial();
            }

            private Material SelectRandomMaterial () {
            return _materials[Random.Range(0, _materials.Length)];
            }

            }


            Attach it to your prefab and now when you spawn them, they will have random materials. You now also have the option to use the same code on non-prefab objects as well. Just don't forget to assign the materials!






            share|improve this answer























            • This was actually super easy to add without changing any of my existing code. Thank you!
              – ls_dev
              Nov 23 at 14:54















            up vote
            1
            down vote



            accepted










            I think mixing the random material behaviour with creation behaviour is overcomplicating things. Just create a component that randomises a GameObject's material on Start and it will run when you instantiate your prefab.



            public class MaterialRandomiser : MonoBehaviour {

            [SerializeField]
            private Material _materials;
            [SerializeField]
            private Renderer _renderer;

            public void Start () {
            ChangeMaterial();
            }

            public void Reset () {
            _renderer = GetComponent<Renderer>();
            }

            public void ChangeMaterial () {
            _renderer.material = SelectRandomMaterial();
            }

            private Material SelectRandomMaterial () {
            return _materials[Random.Range(0, _materials.Length)];
            }

            }


            Attach it to your prefab and now when you spawn them, they will have random materials. You now also have the option to use the same code on non-prefab objects as well. Just don't forget to assign the materials!






            share|improve this answer























            • This was actually super easy to add without changing any of my existing code. Thank you!
              – ls_dev
              Nov 23 at 14:54













            up vote
            1
            down vote



            accepted







            up vote
            1
            down vote



            accepted






            I think mixing the random material behaviour with creation behaviour is overcomplicating things. Just create a component that randomises a GameObject's material on Start and it will run when you instantiate your prefab.



            public class MaterialRandomiser : MonoBehaviour {

            [SerializeField]
            private Material _materials;
            [SerializeField]
            private Renderer _renderer;

            public void Start () {
            ChangeMaterial();
            }

            public void Reset () {
            _renderer = GetComponent<Renderer>();
            }

            public void ChangeMaterial () {
            _renderer.material = SelectRandomMaterial();
            }

            private Material SelectRandomMaterial () {
            return _materials[Random.Range(0, _materials.Length)];
            }

            }


            Attach it to your prefab and now when you spawn them, they will have random materials. You now also have the option to use the same code on non-prefab objects as well. Just don't forget to assign the materials!






            share|improve this answer














            I think mixing the random material behaviour with creation behaviour is overcomplicating things. Just create a component that randomises a GameObject's material on Start and it will run when you instantiate your prefab.



            public class MaterialRandomiser : MonoBehaviour {

            [SerializeField]
            private Material _materials;
            [SerializeField]
            private Renderer _renderer;

            public void Start () {
            ChangeMaterial();
            }

            public void Reset () {
            _renderer = GetComponent<Renderer>();
            }

            public void ChangeMaterial () {
            _renderer.material = SelectRandomMaterial();
            }

            private Material SelectRandomMaterial () {
            return _materials[Random.Range(0, _materials.Length)];
            }

            }


            Attach it to your prefab and now when you spawn them, they will have random materials. You now also have the option to use the same code on non-prefab objects as well. Just don't forget to assign the materials!







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 21 at 23:52

























            answered Nov 21 at 23:30









            CaTs

            58929




            58929












            • This was actually super easy to add without changing any of my existing code. Thank you!
              – ls_dev
              Nov 23 at 14:54


















            • This was actually super easy to add without changing any of my existing code. Thank you!
              – ls_dev
              Nov 23 at 14:54
















            This was actually super easy to add without changing any of my existing code. Thank you!
            – ls_dev
            Nov 23 at 14:54




            This was actually super easy to add without changing any of my existing code. Thank you!
            – ls_dev
            Nov 23 at 14:54












            up vote
            5
            down vote













            After you instantiate the GameObject, get the MeshRenderer from it then change it's material:



            public GameObject eggPrefab;
            public Vector3 spawnPos;
            public Material mat;

            void Start()
            {
            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
            obj.GetComponent<MeshRenderer>().material = mat;
            }


            If you don't have the material then you can create one with a shader and assign it to the MeshRenderer:



            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);

            //Find the Standard Shader
            Material mat = new Material(Shader.Find("Standard"));
            //Set Texture on the material
            //mat.SetTexture("_MainTex", yourTexture);

            obj.GetComponent<MeshRenderer>().material = mat;




            Finally, if you have more than one material then use the materials property instead of the material property and assign your array of material to it:



            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);

            //Find the Standard Shader
            Material mat = new Material(Shader.Find("Standard"));
            //Set Texture on the material
            //mat.SetTexture("_MainTex", yourTexture);

            //Create array of mats (Create one for example)
            Material mats = new Material[1];
            mats[0] = mat;

            obj.GetComponent<MeshRenderer>().materials = mats;


            Edit:



            I missed the random part. If you want random material selection, just use Random.Range to select one item from the array of Material.



            public GameObject eggPrefab;
            public Vector3 spawnPos;
            public Material mats;

            void Start()
            {
            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
            int matIndex = UnityEngine.Random.Range(0, mats.Length);
            obj.GetComponent<MeshRenderer>().material = mats[matIndex];
            }





            share|improve this answer























            • @ls_dev Every time you assign to Renderer.material you're (somehow) assigning a new instance of your material and increasing your number of draw calls. Always use Renderer.sharedMaterial to avoid this.
              – Kevin Remo
              Nov 21 at 21:44






            • 1




              @KevinRemo No. Not every time. It happens once only for each call on the renderer. Aslo, there are times when you need Renderer.material then Renderer.sharedMaterial. It totally depends on what OP is doing because if you have many objects/prefabs referencing one material, Renderer.material should be used to change their individual colors. If you want to change all the color of objects using that material, use Renderer.sharedMaterial. OP may use MaterialBlock to prevent creating new instances but it breaks batching.
              – Programmer
              Nov 21 at 21:51












            • Thank you for the help, I will try this tomorrow and update the thread.
              – ls_dev
              Nov 21 at 22:12






            • 1




              @ls_dev It should be noted that Renderer.material automatically clones materials when its first invoked. Its one of those "does things to be easy on the developer" helper functionalities.
              – Draco18s
              Nov 22 at 4:30















            up vote
            5
            down vote













            After you instantiate the GameObject, get the MeshRenderer from it then change it's material:



            public GameObject eggPrefab;
            public Vector3 spawnPos;
            public Material mat;

            void Start()
            {
            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
            obj.GetComponent<MeshRenderer>().material = mat;
            }


            If you don't have the material then you can create one with a shader and assign it to the MeshRenderer:



            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);

            //Find the Standard Shader
            Material mat = new Material(Shader.Find("Standard"));
            //Set Texture on the material
            //mat.SetTexture("_MainTex", yourTexture);

            obj.GetComponent<MeshRenderer>().material = mat;




            Finally, if you have more than one material then use the materials property instead of the material property and assign your array of material to it:



            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);

            //Find the Standard Shader
            Material mat = new Material(Shader.Find("Standard"));
            //Set Texture on the material
            //mat.SetTexture("_MainTex", yourTexture);

            //Create array of mats (Create one for example)
            Material mats = new Material[1];
            mats[0] = mat;

            obj.GetComponent<MeshRenderer>().materials = mats;


            Edit:



            I missed the random part. If you want random material selection, just use Random.Range to select one item from the array of Material.



            public GameObject eggPrefab;
            public Vector3 spawnPos;
            public Material mats;

            void Start()
            {
            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
            int matIndex = UnityEngine.Random.Range(0, mats.Length);
            obj.GetComponent<MeshRenderer>().material = mats[matIndex];
            }





            share|improve this answer























            • @ls_dev Every time you assign to Renderer.material you're (somehow) assigning a new instance of your material and increasing your number of draw calls. Always use Renderer.sharedMaterial to avoid this.
              – Kevin Remo
              Nov 21 at 21:44






            • 1




              @KevinRemo No. Not every time. It happens once only for each call on the renderer. Aslo, there are times when you need Renderer.material then Renderer.sharedMaterial. It totally depends on what OP is doing because if you have many objects/prefabs referencing one material, Renderer.material should be used to change their individual colors. If you want to change all the color of objects using that material, use Renderer.sharedMaterial. OP may use MaterialBlock to prevent creating new instances but it breaks batching.
              – Programmer
              Nov 21 at 21:51












            • Thank you for the help, I will try this tomorrow and update the thread.
              – ls_dev
              Nov 21 at 22:12






            • 1




              @ls_dev It should be noted that Renderer.material automatically clones materials when its first invoked. Its one of those "does things to be easy on the developer" helper functionalities.
              – Draco18s
              Nov 22 at 4:30













            up vote
            5
            down vote










            up vote
            5
            down vote









            After you instantiate the GameObject, get the MeshRenderer from it then change it's material:



            public GameObject eggPrefab;
            public Vector3 spawnPos;
            public Material mat;

            void Start()
            {
            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
            obj.GetComponent<MeshRenderer>().material = mat;
            }


            If you don't have the material then you can create one with a shader and assign it to the MeshRenderer:



            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);

            //Find the Standard Shader
            Material mat = new Material(Shader.Find("Standard"));
            //Set Texture on the material
            //mat.SetTexture("_MainTex", yourTexture);

            obj.GetComponent<MeshRenderer>().material = mat;




            Finally, if you have more than one material then use the materials property instead of the material property and assign your array of material to it:



            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);

            //Find the Standard Shader
            Material mat = new Material(Shader.Find("Standard"));
            //Set Texture on the material
            //mat.SetTexture("_MainTex", yourTexture);

            //Create array of mats (Create one for example)
            Material mats = new Material[1];
            mats[0] = mat;

            obj.GetComponent<MeshRenderer>().materials = mats;


            Edit:



            I missed the random part. If you want random material selection, just use Random.Range to select one item from the array of Material.



            public GameObject eggPrefab;
            public Vector3 spawnPos;
            public Material mats;

            void Start()
            {
            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
            int matIndex = UnityEngine.Random.Range(0, mats.Length);
            obj.GetComponent<MeshRenderer>().material = mats[matIndex];
            }





            share|improve this answer














            After you instantiate the GameObject, get the MeshRenderer from it then change it's material:



            public GameObject eggPrefab;
            public Vector3 spawnPos;
            public Material mat;

            void Start()
            {
            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
            obj.GetComponent<MeshRenderer>().material = mat;
            }


            If you don't have the material then you can create one with a shader and assign it to the MeshRenderer:



            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);

            //Find the Standard Shader
            Material mat = new Material(Shader.Find("Standard"));
            //Set Texture on the material
            //mat.SetTexture("_MainTex", yourTexture);

            obj.GetComponent<MeshRenderer>().material = mat;




            Finally, if you have more than one material then use the materials property instead of the material property and assign your array of material to it:



            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);

            //Find the Standard Shader
            Material mat = new Material(Shader.Find("Standard"));
            //Set Texture on the material
            //mat.SetTexture("_MainTex", yourTexture);

            //Create array of mats (Create one for example)
            Material mats = new Material[1];
            mats[0] = mat;

            obj.GetComponent<MeshRenderer>().materials = mats;


            Edit:



            I missed the random part. If you want random material selection, just use Random.Range to select one item from the array of Material.



            public GameObject eggPrefab;
            public Vector3 spawnPos;
            public Material mats;

            void Start()
            {
            GameObject obj = Instantiate(eggPrefab, spawnPos, Quaternion.identity);
            int matIndex = UnityEngine.Random.Range(0, mats.Length);
            obj.GetComponent<MeshRenderer>().material = mats[matIndex];
            }






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 21 at 22:02

























            answered Nov 21 at 21:08









            Programmer

            75k1080142




            75k1080142












            • @ls_dev Every time you assign to Renderer.material you're (somehow) assigning a new instance of your material and increasing your number of draw calls. Always use Renderer.sharedMaterial to avoid this.
              – Kevin Remo
              Nov 21 at 21:44






            • 1




              @KevinRemo No. Not every time. It happens once only for each call on the renderer. Aslo, there are times when you need Renderer.material then Renderer.sharedMaterial. It totally depends on what OP is doing because if you have many objects/prefabs referencing one material, Renderer.material should be used to change their individual colors. If you want to change all the color of objects using that material, use Renderer.sharedMaterial. OP may use MaterialBlock to prevent creating new instances but it breaks batching.
              – Programmer
              Nov 21 at 21:51












            • Thank you for the help, I will try this tomorrow and update the thread.
              – ls_dev
              Nov 21 at 22:12






            • 1




              @ls_dev It should be noted that Renderer.material automatically clones materials when its first invoked. Its one of those "does things to be easy on the developer" helper functionalities.
              – Draco18s
              Nov 22 at 4:30


















            • @ls_dev Every time you assign to Renderer.material you're (somehow) assigning a new instance of your material and increasing your number of draw calls. Always use Renderer.sharedMaterial to avoid this.
              – Kevin Remo
              Nov 21 at 21:44






            • 1




              @KevinRemo No. Not every time. It happens once only for each call on the renderer. Aslo, there are times when you need Renderer.material then Renderer.sharedMaterial. It totally depends on what OP is doing because if you have many objects/prefabs referencing one material, Renderer.material should be used to change their individual colors. If you want to change all the color of objects using that material, use Renderer.sharedMaterial. OP may use MaterialBlock to prevent creating new instances but it breaks batching.
              – Programmer
              Nov 21 at 21:51












            • Thank you for the help, I will try this tomorrow and update the thread.
              – ls_dev
              Nov 21 at 22:12






            • 1




              @ls_dev It should be noted that Renderer.material automatically clones materials when its first invoked. Its one of those "does things to be easy on the developer" helper functionalities.
              – Draco18s
              Nov 22 at 4:30
















            @ls_dev Every time you assign to Renderer.material you're (somehow) assigning a new instance of your material and increasing your number of draw calls. Always use Renderer.sharedMaterial to avoid this.
            – Kevin Remo
            Nov 21 at 21:44




            @ls_dev Every time you assign to Renderer.material you're (somehow) assigning a new instance of your material and increasing your number of draw calls. Always use Renderer.sharedMaterial to avoid this.
            – Kevin Remo
            Nov 21 at 21:44




            1




            1




            @KevinRemo No. Not every time. It happens once only for each call on the renderer. Aslo, there are times when you need Renderer.material then Renderer.sharedMaterial. It totally depends on what OP is doing because if you have many objects/prefabs referencing one material, Renderer.material should be used to change their individual colors. If you want to change all the color of objects using that material, use Renderer.sharedMaterial. OP may use MaterialBlock to prevent creating new instances but it breaks batching.
            – Programmer
            Nov 21 at 21:51






            @KevinRemo No. Not every time. It happens once only for each call on the renderer. Aslo, there are times when you need Renderer.material then Renderer.sharedMaterial. It totally depends on what OP is doing because if you have many objects/prefabs referencing one material, Renderer.material should be used to change their individual colors. If you want to change all the color of objects using that material, use Renderer.sharedMaterial. OP may use MaterialBlock to prevent creating new instances but it breaks batching.
            – Programmer
            Nov 21 at 21:51














            Thank you for the help, I will try this tomorrow and update the thread.
            – ls_dev
            Nov 21 at 22:12




            Thank you for the help, I will try this tomorrow and update the thread.
            – ls_dev
            Nov 21 at 22:12




            1




            1




            @ls_dev It should be noted that Renderer.material automatically clones materials when its first invoked. Its one of those "does things to be easy on the developer" helper functionalities.
            – Draco18s
            Nov 22 at 4:30




            @ls_dev It should be noted that Renderer.material automatically clones materials when its first invoked. Its one of those "does things to be easy on the developer" helper functionalities.
            – Draco18s
            Nov 22 at 4:30










            up vote
            1
            down vote













            You could do the following using an materials array.



                public Material materialsArray;
            public GameObject prefab;
            private Vector3 pos = new Vector3(0, 0, 0);
            private Quaternion rot = Quaternion.identity;

            private void Start()
            {
            Material mat = RandomMaterial(materialsArray);
            InstantiateWithMaterial(prefab, pos, rot, mat);
            }

            public Material RandomMaterial(Material _array_)
            {
            return _array_[Random.Range(0, _array_.Length)];
            }

            public void InstantiateWithMaterial(GameObject _prefab_, Vector3 _pos_, Quaternion _rot_, Material _mat_)
            {
            GameObject obj_ = Instantiate(_prefab_, _pos_, _rot_);
            obj_.gameObject.GetComponent<MeshRenderer>().material = _mat_;
            }


            This should work how you want, just place on an empty GameObject and populate the materials array with all the materials you want.






            share|improve this answer

























              up vote
              1
              down vote













              You could do the following using an materials array.



                  public Material materialsArray;
              public GameObject prefab;
              private Vector3 pos = new Vector3(0, 0, 0);
              private Quaternion rot = Quaternion.identity;

              private void Start()
              {
              Material mat = RandomMaterial(materialsArray);
              InstantiateWithMaterial(prefab, pos, rot, mat);
              }

              public Material RandomMaterial(Material _array_)
              {
              return _array_[Random.Range(0, _array_.Length)];
              }

              public void InstantiateWithMaterial(GameObject _prefab_, Vector3 _pos_, Quaternion _rot_, Material _mat_)
              {
              GameObject obj_ = Instantiate(_prefab_, _pos_, _rot_);
              obj_.gameObject.GetComponent<MeshRenderer>().material = _mat_;
              }


              This should work how you want, just place on an empty GameObject and populate the materials array with all the materials you want.






              share|improve this answer























                up vote
                1
                down vote










                up vote
                1
                down vote









                You could do the following using an materials array.



                    public Material materialsArray;
                public GameObject prefab;
                private Vector3 pos = new Vector3(0, 0, 0);
                private Quaternion rot = Quaternion.identity;

                private void Start()
                {
                Material mat = RandomMaterial(materialsArray);
                InstantiateWithMaterial(prefab, pos, rot, mat);
                }

                public Material RandomMaterial(Material _array_)
                {
                return _array_[Random.Range(0, _array_.Length)];
                }

                public void InstantiateWithMaterial(GameObject _prefab_, Vector3 _pos_, Quaternion _rot_, Material _mat_)
                {
                GameObject obj_ = Instantiate(_prefab_, _pos_, _rot_);
                obj_.gameObject.GetComponent<MeshRenderer>().material = _mat_;
                }


                This should work how you want, just place on an empty GameObject and populate the materials array with all the materials you want.






                share|improve this answer












                You could do the following using an materials array.



                    public Material materialsArray;
                public GameObject prefab;
                private Vector3 pos = new Vector3(0, 0, 0);
                private Quaternion rot = Quaternion.identity;

                private void Start()
                {
                Material mat = RandomMaterial(materialsArray);
                InstantiateWithMaterial(prefab, pos, rot, mat);
                }

                public Material RandomMaterial(Material _array_)
                {
                return _array_[Random.Range(0, _array_.Length)];
                }

                public void InstantiateWithMaterial(GameObject _prefab_, Vector3 _pos_, Quaternion _rot_, Material _mat_)
                {
                GameObject obj_ = Instantiate(_prefab_, _pos_, _rot_);
                obj_.gameObject.GetComponent<MeshRenderer>().material = _mat_;
                }


                This should work how you want, just place on an empty GameObject and populate the materials array with all the materials you want.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 21 at 21:22









                Skelly1983

                156213




                156213






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53420416%2fhow-to-dynamically-set-a-random-material-on-a-gameobject%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Berounka

                    Sphinx de Gizeh

                    Different font size/position of beamer's navigation symbols template's content depending on regular/plain...