Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

C# How can I change the texture for an object in C#?

Discussion in 'Scripting' started by From-Soy-Sauce, Sep 12, 2014.

  1. From-Soy-Sauce

    From-Soy-Sauce

    Joined:
    Jan 7, 2014
    Posts:
    162
    Hi I'm working on a Fighting game, and I have gotten to the point where I need the characters to have alt pallets, I wanted to know how to go about making changing the texture for one of them to an alt pallet.

     
  2. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Make alternate materials with the new textures. You will want to find the renderer and switch the materials out. There is a bit of funniness in getting the material vs the sharedMaterial from the renderer, but you should only need to worry about that if you have multiple models that will use the alt material at the same time.
     
  3. From-Soy-Sauce

    From-Soy-Sauce

    Joined:
    Jan 7, 2014
    Posts:
    162
    Ok then the next logical question is: How do I find the renderer and switch the materials out using C#?
     
  4. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Something like this.
    Code (csharp):
    1. public Material newMaterial;
    2.  
    3. void Start()
    4. {
    5.   if (renderer == null)
    6.   {
    7.     Debug.LogWarning("No renderer attached to " + name + "!");
    8.     Destroy(this);
    9.     return;
    10.   }
    11.   renderer.material = newMaterial;
    12. }
    If your model has multiple materials you'll have to replace an array of materials. If you want to switch out the material for all instances of this model, use renderer.sharedMaterial instead of renderer.material.
     
  5. From-Soy-Sauce

    From-Soy-Sauce

    Joined:
    Jan 7, 2014
    Posts:
    162
    Hmmmmmmmmmm.... I've been looking at this code for a while and not really been able to figure out what to do with it.

    Also I should point out my case is a little less than normal. I've got it set so that the model that I want to change the texture to is actually prefab that is instantiated by the player object in the Start method via:
    Code (CSharp):
    1. MyMod=Instantiate(glob.SAKUYA,transform.position,transform.rotation) as GameObject;
    Also there are indeed multiple materials for this character, but I only need to replace 1 of them.
     
  6. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Untested. I think it'll go something like this. The code looks long because I put in a bunch of null checks and warnings so if something goes wrong it'll be easy to know where.

    If there's a simpler way of doing this I'd love to hear it.
    Code (csharp):
    1. public class CreateModelAndSwapMaterial: MonoBehaviour
    2. {
    3.   public Material materialToReplace;
    4.   public Material newMaterial;
    5.  
    6.   void Start()
    7.   {
    8.     MyMod = Instantiate(glob.SAKUYA,transform.position,transform.rotation) as GameObject;
    9.     if (MyMod == null || MyMod.renderer == null)
    10.     {
    11.       Debug.LogWarning("Failure instantiating MyMod or MyMod has no renderer!");
    12.       return;
    13.     }
    14.     SwapMaterial(originalMaterial, newMaterial, MyMod.renderer);
    15.   }
    16.  
    17.   static void SwapMaterial(Material materialToReplace, Material newMaterial, Renderer renderer)
    18.   {
    19.     if (renderer == null || materialToReplace == null || newMaterial == null)
    20.     {
    21.       Debug.LogWarning("Missing material or renderer.");
    22.       return;
    23.     }
    24.     // Using sharedMaterials so we get the original materials
    25.     // instead of a copy of the materials.
    26.     Material[] rendererMaterials = renderer.sharedMaterials;
    27.     if (rendererMaterials == null)
    28.     {
    29.       Debug.LogWarning("Could not find materials on renderer.");
    30.       return;
    31.     }
    32.     for (int n = 0; n < rendererMaterials.Length; n++)
    33.     {
    34.       if (rendererMaterials[n] != null && rendererMaterials[n] == materialToReplace)
    35.         rendererMaterials[n] = newMaterial;
    36.     }
    37.     renderer.materials = rendererMaterials;
    38.   }
    39. }
     
  7. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    This is not quite what Renderer.sharedMaterial does. Accessing Renderer.sharedMaterial gives you a reference to the material asset stored in your project. Editing it by for example changing its color will modify the asset and any other model that uses this material will be affected, since you modify the source.
    Renderer.material on the other hand will return a cloned version of sharedMaterial, this lets you edit the material in runtime without modifying the asset stored in the project.
    If you really do want to switch out the material for all instances of a model, you will have to find them all and replace all their materials with the new one.
     
    GarthSmith likes this.
  8. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    You're absolutely right. I recently used sharedMaterial to tween a color on an existing material shared by many renderers at once, so that's how I was using it.

    Actually replacing the material does not need sharedMaterial, though I still needed it in my latest code example to find the original material in the array.