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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Assigning Material to Every Sub-mesh

Discussion in 'Scripting' started by Johny_G, Jan 19, 2016.

  1. Johny_G

    Johny_G

    Joined:
    Mar 28, 2014
    Posts:
    20
    Hello there!

    We have some spells in our game that are visualized by adding another material to the current one (i.e. layer of ice when enemy is frozen). For most enemies, this works and looks great, but certain models use multiple materials (i.e. one for body and one for weapon, or one for body and one for hair, etc.), which is achieved by creating multiple groups within 3D editing software. Unfortunately, if I add an material to the renderer, it only applies to the first group. Which, in some cases, is just the weapon or the hair.

    Is there any way to mark the target group id/submesh for the newly added material, so I can add it to all of them?

    This is the current code I use:

    Code (CSharp):
    1. public void AddMaterial(Renderer targetRenderer, Material targetMaterial)
    2. {
    3.     if (!targetRenderer || !targetMaterial)
    4.     {
    5.         return;
    6.     }
    7.  
    8.     var dynamicMaterials = new List<Material>();
    9.     for (int i = 0; i < targetRenderer.materials.Length; i++)
    10.     {
    11.         var material = targetRenderer.materials[i];
    12.         if (!material.name.Contains(targetMaterial.name))
    13.         {
    14.             dynamicMaterials.Add(material);
    15.         }
    16.     }
    17.  
    18.     dynamicMaterials.Add(targetMaterial);
    19.  
    20.     var materials = new Material[dynamicMaterials.Count];
    21.  
    22.     for (int i = 0; i < dynamicMaterials.Count; i++)
    23.     {
    24.         materials[i] = dynamicMaterials[i];
    25.     }
    26.  
    27.     targetRenderer.materials = materials;
    28. }
    I'm probably missing something simple and obvious, but I would appreciate any help.

    Thanks a lot!
     
  2. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    multi/sub materials in Unity use the material ID from the 3d software package. changing the order of the materials is a bad idea. This could and probably will have effects like changing the hair texture to be on the weapon.

    What you are trying to do needs to be done at the shader level. So the shader says. Display my texture and/or other properties, and add these effects based on what my game requires. So you let the shader do this in the math.

    You get this by giving the shader a new value. IceAmount or something like that. You then take the ice texture. (which is assigned to every material) and Lerp it onto the rendered texture.
     
  3. Johny_G

    Johny_G

    Joined:
    Mar 28, 2014
    Posts:
    20
    Thank you! The problem is, that we don't have any competent shader developer right now, and this goes beyond my skills.

    I don't really change order of materials. I keep the two that it already had, and add one on top of it. Unity shows the last material on top of the original one (unlike the character material, the ice uses transparent shader with UV animation - it's not just a texture; it looks cool, and it doesn't seem that the extra draw call creates any noticable performance issues). But it only does it on one of the submeshes (after today's investigation it seems that it's actually the last one, not the first - but not sure), even if you add it multiple times. Isn't there any way to assign a material to certain ID, so I can just add two of them and assign them properly?