• RuntimesUnity
  • How to cast Dynamic Shadows on specified layer?

Hi,

I am creating a 2D game in Unity and have set up URP. I want to cast a dynamic shadow from all the objects in my "default" layer onto the layer behind, lets call it "middleground".

In Guacamelee 2 this sort of effect is done, a nice dynamic soft shadow is cast from the characters onto the background. As far as I am aware this game uses Spine for its animations.

I am not very knowledgeable about the nitty gritty of rendering, but I assumed an effect like this would be simpler to achieve. I have been banging my head against the wall for days now trying to find a solution online as well as asking chatgpt just to get overly complicated solutions using custom shaders etc.

Currently from what I understand I need a "ShadowCaster2D" on the object that I want to cast shadows, I can set Target Sorting Layer on this component in order to specify the "middleground", and then when I put a spot light 2D into the scene it should cast shadows of that object on the middleground.

The issue with this it that it only works for Sprites and objects with Sprite Renderer, when I put it on my Spine character (which uses Mesh Renderer) the shadow cast is acting like a rectangle and there are also weird shadows appearing over the character itself, the mesh and animations silhouette are not being respected.

The lights are also at an angle and which makes everything look like an isometric perspective even though I am making a 2D sidescroller, no matter how I rotate or move the light I don't know how to make it right. I don't need many point lights, I want one global light that makes the shadows.

Also, placing a light in my scene affects the overall lighting and makes an area of the screen dark, I don't want this. I just want shadows without any lights, same as Guacamelee 2.

I have been banging my head for days now trying to find a solution, and also asking chatgpt which keeps giving me overly complicated solutions using shaders etc.

Can someone please help me out, I just need step by step instructions on how to make this work.

    Related Discussions
    ...

    To achieve dynamic shadows in Unity using URP for your 2D game, especially when using Spine animations, you need to consider a few key points. First, the ShadowCaster2D component is indeed necessary for casting shadows, but it is primarily designed for static shapes and may not work well with animated Spine characters due to their dynamic nature. For Spine characters, you might need to use a custom shader that supports shadow casting or adjust the existing Spine shaders to write to the depth buffer, as mentioned in the context.

    Here are some steps you can follow to achieve the desired effect:

    1. Use a Compatible Shader: Ensure that your Spine character uses a shader that can write to the depth buffer. You might need to switch to a shader like Spine/Skeleton Lit ZWrite or Spine/Sprite/Vertex Lit and enable "Write to Depth" to allow the character to cast shadows properly.

    2. Shadow Caster Setup: Add a ShadowCaster2D component to your Spine character. You may need to manually define the shadow shape using the "Shape Editor" in the ShadowCaster2D component to match your character's silhouette.

    3. Lighting Setup: If you want shadows without affecting the overall lighting, you can use a global light with minimal intensity or adjust the light's settings to only affect shadows. You can also experiment with the light's angle and position to achieve the desired shadow effect without altering the scene's lighting.

    4. Layer and Sorting: Ensure that your layers are set up correctly. The ShadowCaster2D component allows you to specify the target sorting layer, which should be set to "middleground" in your case.

    5. Avoiding Unwanted Lighting Effects: If the light is affecting the scene's brightness, you can adjust the light's intensity or use a custom shader that only processes shadows without affecting the scene's lighting.

    These steps should help you achieve a similar shadow effect as seen in Guacamelee 2. If you encounter issues with the shadow shape or lighting, you may need to further customize the shaders or explore third-party solutions that offer more advanced 2D shadow casting capabilities.

    This is a standard Ai answer that doesn't help. Using those materials makes the character invisible on top of the shadows not working. Also, I cannot adjust the shape of the shadow in ShadowCaster2D manually, it needs to be set automatically by respecting the silhouette of the animation.

    MadPropz101 Currently from what I understand I need a "ShadowCaster2D" on the object that I want to cast shadows, I can set Target Sorting Layer on this component in order to specify the "middleground", and then when I put a spot light 2D into the scene it should cast shadows of that object on the middleground.

    Judging from the Guacamelee 2 screenshot, you likely don't want to use a ShadowCaster2D setup, as it's for a completely different scenario, casting a pseudo-shadow based on the silhouette (see the screenshots of the documentation here), elongating outwards from the corner vertices with a distance fall-off. Also, it's mainly intended for static Sprites as Spinebot mentioned, not for animated characters.

    What you would need instead based on the screenshot is a true 3D projective shadow, switching from the URP 2D pipeline (with a 2D Renderer) to the normal URP 3D pipeline. Then your middle ground would be positioned at the real depth to automatically receive the respective shadow. You can check out the Spine Examples/Getting Started/5 Basic Platformer example scene for a simple shadow setup, in this case for Built-In Render Pipeline instead of URP 3D.

    Another way where you could use would be to use a copy of the mesh with a black material as a fake-shadow. You can find more details in e.g. the following forum threads:
    https://esotericsoftware.com/forum/d/24502-how-to-make-spine-produce-shadow-similar-to-spine-shape/4
    https://esotericsoftware.com/forum/d/17376-request-dynamic-shadows/3
    or on this thread.

    @Harald I see, but would it be bad performance wise to use URP 3D for a 2D project?
    I converted my project to URP 3D, but now the colors on my Spine character look washed out. When I place the 3D lights into the scene they don't affect anything, neither my sprite objects or Spine objects. Which materials do I need to use? Will the shadows cast onto the surface behind based on the Z world position of the surface and the strength of the light? Do I need to have a light parented to each dynamic game object in order to cast the shadow behind them, or can I have just one global light for the shadows?

      MadPropz101 I see, but would it be bad performance wise to use URP 3D for a 2D project?

      No, why would that be bad for performance?

      MadPropz101 I converted my project to URP 3D, but now the colors on my Spine character look washed out.

      Please check:

      1. The shaders, whether you're using URP 3D shaders everywhere and not URP 2D shaders.
      2. The assigned Render Pipeline Asset in your Project Settings under Graphics, whether everything is properly set up for 3D.
      3. The color space. Decide whether you want to use Linear (default, but unintuitive for typical 2D workflow) or Gamma color space.

      When I place the 3D lights into the scene they don't affect anything, neither my sprite objects or Spine objects.

      This sounds as if your project settings are improperly configured for URP 3D. You can check out the provided URP 2D Shaders and URP 3D Shaders example scenes that come with the Spine URP Shaders package (to be installed in the package manager under Samples). If the URP 3D Shaders example scene is not properly lit, your project setup is likely wrong. You can also try the included Example 3D URP Asset which is included in the package as well next to the URP 3D Shaders example scene.

      MadPropz101 Which materials do I need to use?

      With a URP Render Pipeline Asset active and no 2D Renderer assigned, you need to use URP 3D shaders (as always in Unity).

      MadPropz101 Will the shadows cast onto the surface behind based on the Z world position of the surface and the strength of the light?

      Shadow is the absence of light, and it's also implemented like that. Shadow-map-based shadows don't add the respective light where it is blocked, i.e. in shadow.

      Do I need to have a light parented to each dynamic game object in order to cast the shadow behind them, or can I have just one global light for the shadows?

      Why would you parent a light to each dynamic game object? Please add lights where there are lights, and e.g. use a single directional light if you need a simple light setup and have everything cast a shadow in the same direction.

      Note that these are all general Unity question and nothing specific to Spine or spine-unity. While it may seem tempting to jump ahead, please make sure to get comfortable with Unity's lighting setup first before adding layers of complexity on top by adding animated Spine skeletons. Added complexity makes simple problems more complicated to resolve.