1

I created my first shader by following this video. Dissolve Shader Video Link

In a Coroutine,i took the Material's component from the object:

PalaceMaterial = palaceInstance.GetComponent <Renderer> () .material;

I set the parameter to 0:

PalaceMaterial.SetFloat ("_ CutoffHeight", 0);

To have this effect, I had to modify the parameter "CuttoffHeight" gradually putting it in Update ()

 PalaceMaterial.SetFloat("_CutoffHeight", Mathf.MoveTowards(PalaceMaterial.GetFloat("_CutoffHeight"), CutoffHeight, 100 * Time.deltaTime));

I applied this to all objects. Every 2 seconds i instantiate an "invisible object" (CutoffHeight set to 0) and in Update() it change the value gradually. Now I would like to change this parameter to all objects that use this shader simultaneously. I hope i was clear.

Video of my project : Project, Dissolve_Effect

I would like to change the "_CutoffHeight" parameter simultaneously in all the cubes that are in the first platform, then in the second one, etc. etc. Do you have any idea?

SebyLiberty
  • 47
  • 3
  • 10

1 Answers1

5

In general you shouldn't additionally use GetFloat but rather store the value locally and calculate it from there.


Then this already should work if multiple objects share the exact same material by using e.g.

GetComponent<Renderer>().sharedMaterial.SetFloat(...);

but this works only as long as you don't have multiple instances of the material in your renderers.


There is a way to set a property for all Shaders (which have that property) and their according instances (= Materials) I came across in this thread

To do this you have to

  • Disable "exposed" for the according property. Apparently it only works for properties that are not exposed in the Inspector.

  • Use the generated shader property ID you can find in the Inspector of the shader asset itself.

    You can also retrieve it using Shader.PropertyToID

    You can also change it to match your actual parameter name.

  • Use the global setter methods of the shader like Shader.SetGlobalXY

enter image description here

e.g. in order to set the Spec Brightness you would do

Shader.SetGlobalFloat("Vector1_DD757871", value);

So in your case you could probably have one single controller doing something like

// Need this only if you have to get the initial value once
[SerializeField] private Material PalaceMaterial;

private float currentValue;
private string propertyId;

private void Awake()
{
    propertyId = Shader.PropertyToID("_CutoffHeight");
    currentValue = PalaceMaterial.GetFloat("_CutoffHeight");
}

private void Update()
{
    currentValue = Maths.MoveTowards(currentValue, CutoffHeight, 100 * Time.deltaTime);
    Shader.SetGlobalFloat(propertyId, currentValue);
}
derHugo
  • 83,094
  • 9
  • 75
  • 115
  • I would like to instantiate ex 20 cubes every 10 seconds. These cubes use the shader we are talking about here. I would like to change the shader's parameter only to the first 20 cubes, after 10 seconds, to the other 20. What you said is very interesting, but I can't use it, thanks anyway. My English is not very good. Sorry :) – SebyLiberty Jul 30 '20 at 11:54
  • Oh but then what speaks against using something like `foreach(var instance in spawnedInstances) { instance.GetComponent().material.SetFloat(...); }`? – derHugo Jul 30 '20 at 12:02
  • I added videos, I hope you can understand what I want to do. – SebyLiberty Jul 30 '20 at 12:34