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

How to access Textures via a Material without knowing their names?

Discussion in 'Scripting' started by angrypenguin, Jul 16, 2014.

  1. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,500
    The thread title says it all. I need to access the Textures inside a Material to check something, but have no way of knowing in advance what the texture names may be.

    The Material documentation only lists GetTexture(...) and .mainTexture to access the textures. GetTexture(...) requires either a string name or an int, but the int is called "nameID" which implies that it's not just an index (I'm guessing it's actually a shader property ID). The .mainTexture field's documentation says it just returns a texture with the name "_MainTex", so it's not actually useful.

    I also looked at Shader, but didn't spot anything helpful there.

    For what it's worth, it's perfectly ok if this only works in the Editor. And the Inspector shows the textures in a material, so surely they're accessible.

    What am I missing?
     
    Last edited: Jul 18, 2014
  2. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,500
    Well, I've got my thing working, it just has no way of knowing if it's been hooked up correctly. I guess that for now I can live with making the documentation super clear and pointing out that the component can't check itself for this particular error.

    I just hate assuming things and/or not being able to detect and warn about config errors.
     
  3. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,500
    So... nobody?
     
  4. landon912

    landon912

    Joined:
    Nov 8, 2011
    Posts:
    1,579
    Material.mainTexture will return the main texture set on the material, not a texture named such. Unless I'm misunderstanding your question .mainTexture should be what you're looking for.

    The documentation is a bit confusing, but .mainTexture is the equivalent of using GetTexture(_mainTex); _mainTex being the default diffuse texture in Unity's base shaders.

    So, you should be safe with either one if you're simply trying to get the diffuse texture from the material.
     
  5. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,500
    Straight from the documentation, .mainTexture is:
     
  6. landon912

    landon912

    Joined:
    Nov 8, 2011
    Posts:
    1,579
    And _mainTex is the shader variable for the diffuse texture. It'll return the correct base texture.
     
  7. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,500
    Assuming everyone exclusively uses shaders where the naming conventions match those of Unity. I'm not convinced that's a safe assumption considering how much trouble Material.color has given me over the years, even when sticking to Unity's included shaders.

    As I said, I already have this functioning. The purpose here is to make it more robust and self-documenting.
     
  8. landon912

    landon912

    Joined:
    Nov 8, 2011
    Posts:
    1,579
    Yes, I believe you are making that assumption if using GetTexture(). However, .mainTexture MAY return the diffuse texture under any naming convention. It's been a while since I've used either, and as you can see the documentation is lacking, so I can't be sure without further testing. Maybe someone more intelligent then me can give you a definite answer on that.
     
  9. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,500
    I can be sure. I just did further testing which verified that .mainTexture works exactly as the documentation says it does.
     
  10. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    Unfortunatly I've been searching for some enumerating method for shader properties aswell but havnt had luck. I've been solving the issue by just going throught a couple of shaders and getting the respective texture property names out of them. For any further bonus texture a user wants to have included, I simply offer a setup scriptableobject which said users can than modify to fit their needs. EG. Setups local to each component or generally a global setup which is the default.

    Works great with BatchMan! ;)
     
  11. landon912

    landon912

    Joined:
    Nov 8, 2011
    Posts:
    1,579
    Out of curiosity what does .mainTexture contain when such a property doesn't exist in the shader? Is it simply null?
     
  12. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,500
    Yep. I suspect that it doesn't actually "contain" anything, in truth, but is actually a property that wraps Get/Set calls, much the way that GameObject has a bunch of convenience properties that call GetComponent.
     
  13. Sharp-Development

    Sharp-Development

    Joined:
    Nov 14, 2013
    Posts:
    353
    ILSpy:
    Code (CSharp):
    1. // UnityEngine.Material
    2. public Texture mainTexture
    3. {
    4.     get
    5.     {
    6.         return this.GetTexture("_MainTex");
    7.     }
    8.     set
    9.     {
    10.         this.SetTexture("_MainTex", value);
    11.     }
    12. }
    13.  
     
    angrypenguin and Magiichan like this.
  14. MediaGiant

    MediaGiant

    Joined:
    Sep 14, 2013
    Posts:
    304
    Better late than never :)

    Code (CSharp):
    1.  
    2. string[] shaderPropertyTypes = new string[] {"Color", "Vector", "Float", "Range", "Texture"};
    3.  
    4. int propertyCount = ShaderUtil.GetPropertyCount(shader);
    5.                  
    6. for (int index = 0; index < propertyCount; ++index)
    7. {
    8.     Debug.Log(ShaderUtil.GetPropertyName(shader, index) + "      "
    9.     + shaderPropertyTypes[(int)ShaderUtil.GetPropertyType(shader, index)]);
    10. }
    11.  
     
    minjujuu, Zenix and angrypenguin like this.