• Unity
  • Overlay color does nothing in URP shader?

  • Изменено
Related Discussions
...

Hi!

Just checking if it's only me, "Overlay Color" doesn't seem to change anything in the Universal Render Pipeline shader? (Universal Render Pipeline/2D/Spine/Sprite).
The goal was to fill the character with a color, like a "flash" for hit effects, but I suspect this isn't the way to go. I am aware of the "Freeze Boy" example scene and other forum posts, but they don't cover how to go about this with a lit shader. I know I can change the albedo color via MaterialPropertyBlock but this is only for white, and not black in the lit shaders (?).

Edit: just brainstorming, is it a bad idea to either 1. change the material to a Skeleton Tint during runtime and then back to my lit shader every hit? or 2. Make a new "flash" animation in Spine with the slots changing colors, and in Unity making it play on its own layer/track?

Anything in the right direction is very appreciated,
Peter

Just checking if it's only me, "Overlay Color" doesn't seem to change anything in the Universal Render Pipeline shader? (Universal Render Pipeline/2D/Spine/Sprite).

Not sure what the Overlay Color is, so maybe someone else can chime in with this part.

I know I can change the albedo color via MaterialPropertyBlock but this is only for white, and not black in the lit shaders (?).

Correct, if you set a MPB for "_Color" it will tint (not fully "colorize" it).

1. change the material to a Skeleton Tint during runtime and then back to my lit shader every hit? or

This is what I do (I do the same white-flash on enemies when they get hit). I have a separate "colorize" material (using Spine/Skeleton Tint with both colors set to white) for each character, and then keep track of the SkeletonAnimation's original "default" material. I use skeletonAnimation.CustomMaterialOverride to set it to the "colorize" material for like 0.05s and then reset it back to the "default" material.

2. Make a new "flash" animation in Spine with the slots changing colors, and in Unity making it play on its own layer/track?

You could do this, but it would require Tint Black to be enabled and used when setting the Slot colors in order to make the images actually turn fully white (and not just get tinted regularly). I also believe there is a separate Spine shader for Tint Black, so it might not be necessary if you're only using it for the white-flash.

Thanks for the reply!

I’m just learning the Shader Graph, I’m new to Shaders overall. Do you think I can use the Shader Graph for this? Like this tutorial: https://youtu.be/93jnsgD-8Wo

Or is it something with Spine/Skeletons in Unity that makes it important to stick to Spines own shaders?

PeterBacall написал

Thanks for the reply!

I’m just learning the Shader Graph, I’m new to Shaders overall. Do you think I can use the Shader Graph for this? Like this tutorial: https://youtu.be/93jnsgD-8Wo

Or is it something with Spine/Skeletons in Unity that makes it important to stick to Spines own shaders?

I have a decent bit of experience with spine/shaders, but I'm not sure if I can answer that question completely. I do believe that if you're making a 'standard' 2D game without special lighting or anything, that you could actually use Unity's default Sprite shader for spine animations, so that leads me to believe that there is some flexibility with what shaders you can use. However, there are definitely some things that are specific to Spine (such as Tint Black, if you were to use that) that would probably require using the Spine shader. I'm using URP with the 2D Renderer with 2D-Lights, and I definitely need the specific Spine shader for that.

I haven't used Shader Graph, but I have taken one of the Spine shaders and duplicated it, and then added stuff to it. I'm not sure if there is a way to convert/open a normal HLSL shader with Shader Graph? :think:

I tried Shader Graph and it did work fine apparently, but I can't change the parameters (e.g Color, Alpha etc) by code because Spine keeps resetting my material with the original from assets. Is this why "skeletonAnimation.CustomMaterialOverride" is needed? I tried to read some posts and guides but I couldn't get it to work. :/ Any help would be very appreciated, my code so far:

SkeletonAnimation skeletonAnimation;
public Material originalMaterial;
public Material replacementMaterial;

void Start()
{
    skeletonAnimation = GetComponent<SkeletonAnimation>();

//This is where I suspect the problem to be, this only adds my material to the "slot" but doesnt access it in it's original place?
originalMaterial = GetComponent<MeshRenderer>().material;
}

void Update()
{
    if (Input.GetKeyDown(KeyCode.K))
    {
        skeletonAnimation.CustomMaterialOverride.Add(originalMaterial, replacementMaterial);
    }
}

Edit: I also tried this code, and don't know the difference

skeletonAnimation.CustomMaterialOverride[originalMaterial] = replacementMaterial;

Yeah, I'm not sure all of the specifics but the SkeletonAnimation definitely sets some parameters on the Shader, including Color (which includes Alpha).

You can set the color (tint + alpha) with skeletonAnimation.skeleton.SetColor(). I'm assuming it sets "_Color" in whichever shader is being used.

This is my code for changing the material to the "colorizing" one (which uses the Spine/Skeleton Tint shader)

  //I set both of these by dragging the material into the Inspector
public Material defaultMaterial; 
    public Material colorizeMaterial;
public virtual void SetMeshRendererMaterial(Material material) {
    skeletonAnimation.CustomMaterialOverride[defaultMaterial] = material; //Overriding the defaultMaterial with whichever Material you pass in
}
public virtual void SetMeshRendererMaterialToColorize() {
    SetMeshRendererMaterial(colorizeMaterial);
}

public virtual void SetMeshRendererMaterialToDefault() {
    SetMeshRendererMaterial(defaultMaterial);
}

Edit: Worth noting that all of my SkeletonAnimations only use 1 material. If your images aren't all packed into a single atlas than you might be using multiple materials on a single SkeletonAnimation.

Sorry for the late reply. Thanks very much @Jamez0r for helping out in the meantime!

Just checking if it's only me, "Overlay Color" doesn't seem to change anything in the Universal Render Pipeline shader?

Please note that the Overlay Color alpha value determines the intensity, so if you leave it at zero, you receive zero overlay.

This parameter is indeed a bit unfortunate. I will change the Inspector name to Overlay Color & Alpha, I hope this prevents further confusion. Unfortunately the default value needs to stay at alpha=0 since Color Adjustment enables all modifications (hue, saturation, brightness) at once.

Using MaterialPropertyBlock would be a good way of setting such flash overrides, so no need to change code to material switching.

Harald написал

Sorry for the late reply. Thanks very much @Jamez0r for helping out in the meantime!

Just checking if it's only me, "Overlay Color" doesn't seem to change anything in the Universal Render Pipeline shader?

Please note that the Overlay Color alpha value determines the intensity, so if you leave it at zero, you receive zero overlay.

This parameter is indeed a bit unfortunate. I will change the Inspector name to Overlay Color & Alpha, I hope this prevents further confusion. Unfortunately the default value needs to stay at alpha=0 since Color Adjustment enables all modifications (hue, saturation, brightness) at once.

Using MaterialPropertyBlock would be a good way of setting such flash overrides, so no need to change code to material switching.

MaterialPropertyBlock did the job!
Leaving code here if someone else stumbles on this in the future. Not perfect but works for me. Note that I used Shader Graph and created my own shader. I tested if my character has several materials and it changes all of them (which is good). It also seems to work perfectly fine with Shader Graph as long as you name the references _Color, _Black and so on... keep in my mind my coding skills are very amateur. Thank you @Jamez0r and @[удалено]

   
public Color whiteColor = Color.white; public Color blackColor = Color.black; //change this to whatever color in inspector, or white for white flash public float flashDuration = 0.05f; public string colorProperty = "_Color"; public string blackTintProperty = "_Black"; private bool flashing = false; MaterialPropertyBlock block; MeshRenderer meshRenderer; public void Flash() { StartCoroutine(flashCoroutine()); } IEnumerator flashCoroutine() { if (flashing) yield break; flashing = true; block = new MaterialPropertyBlock(); meshRenderer = GetComponent<MeshRenderer>(); block.SetColor(colorProperty, whiteColor); block.SetColor(blackTintProperty, blackColor); meshRenderer.SetPropertyBlock(block); yield return new WaitForSeconds(flashDuration); block.SetColor(colorProperty, Color.white); block.SetColor(blackTintProperty, Color.black); meshRenderer.SetPropertyBlock(block); flashing = false; yield break; }

You're welcome, glad to hear you've figured it out!

2 месяца спустя

Thanks for posting! Really helped.

Thought: if you cache two material blocks at class lvl then switch them each flash, then you can avoid making a new MaterialBlock each time.