Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  4. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Changing the material of renderer works in editor, but not after building app

Discussion in 'Scripting' started by BjoBor, Jul 13, 2018.

  1. BjoBor

    BjoBor

    Joined:
    Jul 13, 2018
    Posts:
    4
    I am using this code to change the material of my player (a basic sphere) in a customise scene of my game.

    Code (CSharp):
    1.     public Material[] material;
    2.     Renderer rendPlayer;
    3.  
    4.     void reload(){
    5.         SceneManager.LoadScene("Customise");
    6.     }
    7.  
    8.     public void Mat1 () {
    9.         rendPlayer = GetComponent<Renderer> ();
    10.         rendPlayer.sharedMaterial = material [0];
    11.  
    12.         reload ();
    13.     }
    I currently have 6 buttons assigned to 6 different voids (Mat1-6). I have 6 different materials assigned to the Material array in the inspector of the script attached to the Player. All of this works when i test it using unity Remote 5, but when i build and install the app it no longer works. I can see that the button works because the scene stutters when the reload() void is activated.
    Does anyone know why this would work in the editor but not after building?
     
  2. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    344
    My guess would be somewhere you're modifying a material Asset directly, which is fine (well, allowed at least) in the editor, but in a build those get frozen. But try changing from sharedMaterial to just material. In theory sharedMaterial is faster for when you know you'll never modify it, but it always causes problems for me.
     
    BjoBor likes this.
  3. BjoBor

    BjoBor

    Joined:
    Jul 13, 2018
    Posts:
    4
    I tried to change it to material instead of sharedMaterial, but the same problem still persists.
    Code (CSharp):
    1.     public Material[] material;
    2.     public Renderer PlayerRenderer;
    3.  
    4.     void reload(){
    5.         SceneManager.LoadScene("Customise");
    6.     }
    7.  
    8.     public void Mat1 () {
    9.         PlayerRenderer.material = material [0];
    10.         reload ();
    11.     }
    I don't really know what you mean by "modifying a material asset directly", so I may be doing it without my knowledge.
    Thank you for your response!
     
  4. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    344
    When you use dot-material, the system creates an instance -- it will say (instance) when you look at it. Those are regular things you can change. Whereas sharedMaterial links directly to the original material, in your Assets area. I think changing those during Play permanently modifies them (running in the Editor). I"m not sure how public Material[] M; works, as far as changing them.

    But I'm just thinking of what could be different between Editor and a Build. It could be anything. I suppose if I had to, I'd make a mini-Project that only did the material swap, checking if it worked or didn't in build.
     
    BjoBor likes this.
  5. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    657
    Since you said this was a material on your player object, I'll assume that the object isn't Static. I think that would cause issues in a build.

    What shader are you using for this material? If it's not one of Unity's built-in shaders, sometimes adding it to the list of shaders to always include has resolved weird build-only issues. (You can add the shader to Always Included in the Graphics settings page).
     
    BjoBor likes this.
  6. BjoBor

    BjoBor

    Joined:
    Jul 13, 2018
    Posts:
    4
    I am using the built-in shader. I have tried creating many different scripts in all ways i can think of, but nothing works after building.
    On the moving gameobject "Player" I am able to change the material in another script, but for some reason I can't change any materials on the same renderer in this script.
    The only difference i see is that this void is activated by a button rather that an If() that checks something every frame.

    This is the code that does not work after building and is activated by a button:
    Code (CSharp):
    1.     public Renderer PlayerRenderer;
    2.     public ParticleSystemRenderer rendParticle;
    3.     public Material MatOne, MatTwo, MatThree, MatFour, MatFive, MatSix;
    4.  
    5.     void reload (){
    6.         SceneManager.LoadScene("Customise");
    7.     }
    8.  
    9.     public void CustomOne(){
    10.         rendParticle.material = MatOne;
    11.         PlayerRenderer.material = MatOne;
    12.         reload ();
    13.     }
    This is the code that works on the same renderer, but in another script:
    Code (CSharp):
    1.     public void gamewin(){
    2.         if (_GameOver == false) {
    3.             popup = "Victory";
    4.             rendParticle.material= matGreen;
    5.             rendParticle.trailMaterial = matInvis;
    6.             PlayerRenderer.material = matGreen;
    7.             PlayerParticle.Play ();
    8.             _GameWin = true;
    9.         }
    10.     }
     
  7. BjoBor

    BjoBor

    Joined:
    Jul 13, 2018
    Posts:
    4
    Okay, so after many hours I finally figured out a workaround!
    Since I was able to change the material of the player elsewhere in the same script i decided it had something to do with the public void i tried to do it in.
    Instead of changing the material when the button was pressed i decided that the buttons should change an int that decides the material in a case that is updated every frame.

    Code (CSharp):
    1. public static int MatCustom=0;
    2. public Renderer PlayerRenderer;
    3. public Material[] Mat;
    4.  
    5. //These are activated by the buttons
    6.     public void Custom1(){
    7.         MatCustom = 1;
    8.     }
    9.  
    10.     public void Custom2(){
    11.         MatCustom = 2;
    12.     }
    13.  
    14.     void Update () {
    15.  
    16.         switch (MatCustom)
    17.         {
    18.         case 1:
    19.             PlayerRenderer.material = Mat[0];
    20.             break;
    21.         case 2:
    22.             PlayerRenderer.material = Mat[1];
    23.             break;
    24.         default:
    25.            
    26.             break;
    27.         }
    28. }
    29.  
    30.  
    I have no idea if this uses any noticeable amount of resources to update every frame, neither do I have any idea why this is the only method I got working
     
  8. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    344
    If that fixed it (changing to the texture you want, over and over again,) it probably means the actual problem is that you're accidentally changing the material back, somewhere else in the program. If it was a real bug, setting it 10 times in a row wouldn't do any more good than doing it once -- it's not as if you can hammer the material in like a nail.

    Why only in a build? It could be a timing issue -- a build often has a different framerate, which changes the order of update vs. fixedUpdate and so on.
     
    BjoBor likes this.