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

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?

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.

So… nobody?

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.

Straight from the documentation, .mainTexture is:

And _mainTex is the shader variable for the diffuse texture. It’ll return the correct base texture.

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.

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.

I can be sure. I just did further testing which verified that .mainTexture works exactly as the documentation says it does.

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! :wink:

Out of curiosity what does .mainTexture contain when such a property doesn’t exist in the shader? Is it simply null?

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.

ILSpy:

// UnityEngine.Material
public Texture mainTexture
{
    get
    {
        return this.GetTexture("_MainTex");
    }
    set
    {
        this.SetTexture("_MainTex", value);
    }
}
2 Likes

Better late than never :slight_smile:

string[] shaderPropertyTypes = new string[] {"Color", "Vector", "Float", "Range", "Texture"};

int propertyCount = ShaderUtil.GetPropertyCount(shader);
                  
for (int index = 0; index < propertyCount; ++index)
{
    Debug.Log(ShaderUtil.GetPropertyName(shader, index) + "      "
    + shaderPropertyTypes[(int)ShaderUtil.GetPropertyType(shader, index)]);
}
3 Likes