Resources.Load and Procedural Materials

Hey Guys! :),

So I’ve been searching on how to load a procedural material via scripting and assign it to a material and I havent just been able to find anything :/.

checkout the image attached.

So basically I’m trying to load a procedural material created with the bitmap2material substance and It just dont work! I’ve tried

ProceduralMaterial m = Resources.Load("Bitmap2Material") as ProceduralMaterial;

and also

ProceduralMaterial m = Resources.Load("Bitmap2Material/Impenetrable") as ProceduralMaterial;
// also
ProceduralMaterial m = Resources.Load("Bitmap2Material/Impenetrable.sbar") as ProceduralMaterial;

and I just CANT load the procedural material!!! >_<

any help would be really appreciated guys :slight_smile:

Cheers
Juan

Resources.Load won’t work with substances because it’s a special case where you have potentially multiple resources (ProceduralMaterial) in another resource which is the .sbsar file itself.

You should try creating a new folder in your resource folder, put your sbsar in it and then call

Resources.LoadAll("MySubstanceFolder", ProceduralMaterial);

then go retrieve your procedural material in the list of objects returned. It should work even though I agree it’s not convenient…

Jerc,

Thanks for the answer! :smile:, but I’m a little bit concerned about the “not convenient” of this method.

Why do you say its not convenient?, I need to load this on the fly as everything I’m programming is loaded from code so I cannot place any procedural material on the inspector + I dont like to loose references :stuck_out_tongue_winking_eye: :wink:

Its not convenient cause it might load more than you want if the materials aren’t split optimally and it requires that you scatter them through folders for it to work. otherwise the consequence of loading can be heavy enough impact wise to make you wish you had them just present in a manager class to request them.

damn dreamora :(, that just sucks :/… and more for me as I’m used to load everything from code!, oh well, I shall load the materials to a GO and then create a manager to provide them…

Thanks dreamora and jerc! :smile:

I bought the Bitmap2Material yesterday, which is a neat tool, but have been trying to get something to work with success yet. I created a Bitmap2Material the way I want in the Unity editor, and what I want to do is apply that specific Bitmap2Material to different textures at runtime, and then assign the resulting materials to different meshes.

For example, if I have 3 different textures that I want to apply to the 3 plane meshes, and I have one Bitmap2Material which I want applied to each texture to generate its normals, etc., how would I make that happen at runtime? Note: I don’t want to create 3 Bitmap2Material instances in the Unity editor because the Bitmap2Material settings are identical for the 3 textures.

Here is what I have tried:

Step 1 – get the main ProceduralMaterial that I want applied to all textures:

Object[] procedureMaterialObjects = Resources.LoadAll("Substances", typeof(ProceduralMaterial) );
				
ProceduralMaterial substance = (ProceduralMaterial) procedureMaterialObjects[0];

Step 2 – Clone a new instance of substance, and then set the textures on this new instance, call RebuildTexturesImmediately to generate the normals, etc., then apply the clone to mesh planes*:*
```
*for (int i=0; i < planes.Length; i++) {
ProceduralMaterial tempSubstance = (ProceduralMaterial) Instantiate(substance);

//Set the texture[i]:
tempSubstance.mainTexture = textures[i];

//Set the diffuse texture - THIS DOES NOT WORK when Instantiate is used:
tempSubstance.SetProceduralTexture(“Bitmap_Diffuse”, textures[i]);

tempSubstance.RebuildTexturesImmediately();

planes[i].renderer.material = tempSubstance;
}*
* <em>The above code does not work because tempSubstance.SetProceduralTexture("Bitmap_Diffuse", textures*); does nothing when a new instance is created using Instantiate. For some reason Instantiate does not appear to clone the entire object.*</em> <em>*Note that I also tried not using Instantiate, and resused the substance, but the problem is that all meshes will have the final texture applied to all of the time (i.e. the mainTexture and Bitmap_Diffuse is written over each time, so the last texture in the loop ends up showing on all meshes):*</em> _*_
*for (int i=0; i < planes.Length; i++) {

//Set the texture[i]:
substance.mainTexture = textures[i];

substance.SetProceduralTexture(“Bitmap_Diffuse”, textures[i]);

substance.RebuildTexturesImmediately();

planes[i].renderer.material = substance;
}
_
```*_
I suppose I could manually go in the Unity editor, and ctrl-D duplicate many instances of the Bitmap2Material, and at runtime assign each texture to each Bitmap2Material (i.e each texture would have to have a corresponding Bitmap2Material predefined in the Unity editor), and then apply them to the object. But this is a silly way to do this – I should be able to make clone copies of the Bitmap2Material at runtime and use them to create the normals, etc. for different textures.
Any suggestions would be appreciated! Thanks!

You don’t have to use Instantiate with ProceduralMaterials.

You need to use first MyObject.renderer.material = substance;

This will create an instance of the substance for this specific object as opposed as SharedMaterial which will just attach the substance to the renderer.

Then you can store ths instance using simply ProceduralMaterial substanceInstance = MyObject.renderer.sharedMaterial as ProceduralMaterial;

Only after having done that you can call your parameter changes and RebuildTextures() on your new substanceInstance in the end.

Jerc, Thanks for the response. That makes sense.

It works now :smile:, with two minor changes to your suggestion – when I retrieved the material I used the material instance instead of the sharedMaterial:

ProceduralMaterial substanceInstance = planes[i].renderer.material as ProceduralMaterial;

Also, I call

substanceInstance.RebuildTexturesImmediately(); instead of substanceInstance.RebuildTextures(); since for this basic test I’m running it synchronously.

The only major problem I have now (as I mentioned in this forum) is that when I try to do a FlashBuild Unity, Unity can’t see the ProceduralMaterial class:
Error: The type or namespace name `ProceduralMaterial’ could not be found. Are you missing a using directive or an assembly reference?

Hopefully the ProceduralMaterial class will be supported for Flash builds in the near future.

Thanks again.

Just googled this question and landed here. To answer the first question, it works for me using the “typeof” overload:

Utilities.defaultMaterial = Resources.Load (“Materials/DefaultMaterial”, typeof(ProceduralMaterial)) as ProceduralMaterial;