Jump to content
Unity Insider Forum
Jomnitech

Shader Einstellungen runtime ändern (gelöst)

Recommended Posts

Hallo Zusammen

Kann mir jemand sagen wie man den Standard Unity Shader via Script von Opaque auf Fade umstellen kann? Finde im Netz irgendwie nichts dazu.

Hintergrund ist wie folgt:
Ich möchte das zerstörte Objekte langsam ausblenden. Wenn ich aber den Shader standardmässig auf Fade stelle, sieht man keine Schatten auf den Objekten, dadurch wirken sie etwas deplaziert. Wenn die Objekte zerstört werden, soll die Shadereinstellung der einzelnen Objekte geändert werden, weil irgendwie für deses Objekt zwei Materials mit verschiedenen Einstellungen zu machen find ich irgendwie doof.

Oder gibt es eine elegantere Lösung?

Share this post


Link to post
Share on other sites

https://forum.unity.com/threads/access-rendering-mode-var-on-standard-shader-via-scripting.287002/#post-1961025

Es funktioniert, aber ich muss zugeben, dass ich das immer ein bisschen gruselig fand. Nach meinem Verständnis kompiliert Unity so viele Varianten des Standard-Shaders, wie du in deinem Projekt benutzt. Wenn du z.B. nur ein Material im Build hast, dann dachte ich immer, dass Unity genau eine Variante des Standard Shaders kompiliert, der genau die Features hat, die das Material benutzt. Zur Laufzeit die Keywords des Shaders umzustellen, müsste demnach bedeuten, dass der Shader on the fly rekompiliert werden muss. Vielleicht geht das einfach schnell genug (könnte sein, wenn man sich mal anschaut, wie schnell der Editor die Dinger kompiliert), vielleicht hab ich da aber auch was übersehen :)

In jedem Fall würde ich sagen: Einmal im Build testen, ob da alles glatt geht.

Sieh an, kurzes Nachlesen hilft :D

https://docs.unity3d.com/Manual/SL-MultipleProgramVariants.html

Kurz gesagt: Jede Variante eines Multi-Compile-Shaders ist immer im Build vorhanden, d.h. man hat Dutzende Varianten des Standard-Shaders jederzeit zur Verfügung und kann mit Material.EnableKeyword oder Shader.EnableKeyword und ihren Disable-Verwandten nach Belieben zwischen ihnen hin und her wechseln.

  • Like 1

Share this post


Link to post
Share on other sites

Erst mals vielen Dank für deine Antwort.
Bekomme das aber irgnedwie nicht richtig hin. Habe es zwar soweit dass er Runtime den Shader auf Fade wechselt, aber dann ändert er das Material grundlegend für alle, statt ein neues Material zu generieren.
Aus den ganzen Disable- und EnableKeywords bin ich nicht schlau geworden, hat sich irgendwie nie etwas getan. Nur

material.SetFloat("_Mode", 2.0f);

hat dan den Mode auf Fade geändert. Aber wie gesagt, ändert ers eben für alle Objekte die das Material teilen.

Share this post


Link to post
Share on other sites

Wenn du eine Material-Variable hast:

public Material material;

und du zeihst da ein Material rein, dann änderst du das Material. Wenn du eines aus den Assets hineinzeihst, dann wird eben das geändert, und alle Renderer, die das Material benutzen, kriegen die Änderungen ab.

Das gleiche passiert, wenn du Renderer.sharedMaterial benutzt - da geht es dann um das Material, das beim Renderer reingezogen wurde.

Wenn du allerdings Renderer.material benutzt, dann sprichst du eine lokale Kopie des Materials an, die der Renderer für sich behält. Machst du also das hier:

private Material material;

private void Awake()
{
  material = GetComponent<Renderer>().material;
}

kannst du im Anschluss mit "material" arbeiten, und es gilt nur für den einen Renderer.

  • Like 1

Share this post


Link to post
Share on other sites

@Sascha

Hatte ich anfangs sogar gemacht, aber hatte dann immer nullReference Fehler(wahrscheinlich irgendwo vertippt), deswegen habe ich dann das Material direkt reingezogen, dachte mir wenn ich das Material direkt vom ChildObjekt selbst wähle klappt das schon.

Wie auch immer, funktioniert soweit, generiert nur leider massig DrawCalls.

Share this post


Link to post
Share on other sites

Du hast vermutlich lauter Material-Instanzen rumfliegen, und die kann Unity nicht batchen. Haben die meisten Renderer dasselbe Material, bis es durch dein Script abgeändert wird? Wenn ja, mach einfach zwei Materials und mache

Renderer.sharedMaterial = anderesMaterial;

anstatt lauter Instanzen zu erzeugen.

Share this post


Link to post
Share on other sites

Ja, hat alles das selbe Material, die Batches sind auch i.O. bis es vom Script auf Fade gesetzt wird, dann scheint es für jedes Objekt ein separates Material zu erzeugen ohne diese zu batchen.
Also lässt sich das wohl via Script nicht so einfach lösen. Dann lass ich das wie gehabt und wie du sagst eben mit zwei Materials.

Trotzdem vielen Dank für deine Antwort.

 

Share this post


Link to post
Share on other sites

Falls es jemanden interessiert, habe ich hier eine Lösung gefunden, mit der man Objekte langsam verschwinden lassen kann und das Objekt trotzdem noch Schatten receivet (was bei Transparent ja nicht der Fall ist) und keine zusätzliches Material benötigt und keine zusätlichen Drawcalls verursacht:

Hiermit lässt sich der Gewählte Cutout Shader ganz einfach Runtime modifizieren(am schönsten wird mit einem Double Side Shader) ohne die Batches zu nichte zu machen.
 

rend.material.SetFloat("_Cutoff", cutoutValue);

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×