Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice
  2. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  3. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Tilemaps Shadow Caster (experiment)

Discussion in '2D Experimental Preview' started by BrianCraig, Nov 26, 2020.

  1. BrianCraig

    BrianCraig

    Joined:
    Apr 13, 2020
    Posts:
    6
    Hi! I've been working on some Shadow casting on Tilemaps component, it is purely experimental, based on the actual Experimental Shadow Caster 2D. I've got a Demo usage:
    . It uses the physics of the Tilemap via a composite collider to generate the shadows.

    For usage:
    Download the repo https://github.com/BrianCraig/Tilemap-Shadow-Caster, and add it somewhere in your project.
    Add the component Tilemap Shadow Caster to a component with the Tilemap and a composite collider 2D.

    If someone uses it and has some feedback or some error please let me know so i can help.

    Brian
     
    Oranger97, mgear and NotaNaN like this.
  2. gPerry

    gPerry

    Joined:
    Nov 27, 2013
    Posts:
    21
    So I just tried this out and it seems to work really well. It looks like you are using the changing state of the 'self shadow' option to trigger a refresh of the shadow meshes. Maybe it would be better as a button via a custom inspector?

    *Edit- ignore that, I misunderstood what SerializedObject was doing. I get it now.

    I'm just wondering, in the video clip you seem to have two shadow layers, allowing you to light up the facing edges of the tiles where the light hits. I can only see one tile layer in the hierarchy and nothing special in the inspector. How did you achieve this effect?
     
    Last edited: Dec 14, 2020
  3. BrianCraig

    BrianCraig

    Joined:
    Apr 13, 2020
    Posts:
    6
    Hi gPerry!

    I'm really glad you tried out, and thanks for the feedback!

    In that case, I am showing the only property that I added to the component, that determines if each of it's shadows paths are self shadows or not, and ends up regenerating each autogenerated native unity shadow caster 2d component, when you change it. Note that the demo is running on Unity edit mode, so sometimes changes are not automatic, afaik it should autogenerate the shadows on run mode when the compositecollider2d updates his collisions (through a tile change).

    In the demo you may note on the left side, that it creates children game objects to the attached component game object, one for each collision path determined by the composite collider, and each one has a component that extends from the shadow caster 2D, which gives the shadow, this is the best option I could achieve with my first experience making a unity component.

    I personally had a rough time trying to make custom component inspectors by my lack of experience, but I'll try to focus on that.

    I hope that clears you some questions, don't hesitate on share me more doubts,

    Thanks, Brian
     
    NotaNaN likes this.
  4. gPerry

    gPerry

    Joined:
    Nov 27, 2013
    Posts:
    21
    Thanks for responding. I was editing my post as you were writing yours :) I worked out what SerializedObject was doing, and that my initial understanding of the script was incorrect. I can see now that it automatically updates, just sometimes a little slowly. This was after I went and added an entirely useless inspector button to the script!

    I'm still not sure how you achieve the rim lighting effect in your example though. I'm referring to the fact that the edges of the tiles facing the light source are lit and cast their own additional shadow. The best place to spot it is the corner just above and to the left of the character, about 8 seconds in to the video.
     

    Attached Files:

  5. BrianCraig

    BrianCraig

    Joined:
    Apr 13, 2020
    Posts:
    6
    Hi Gperry!

    The lightning effect that is being applied is no more than a result of the colliders zone, which is from the original tileset collisions from the official 2d experimental github demo, i attached a photo of the actual collider zone.

    i imagine that it would be useful to add a scene demo on the repo, (and a readme also that i forgot).

    I much appreciate the feedback, Brian
     

    Attached Files:

  6. Mysterious_Mind

    Mysterious_Mind

    Joined:
    Dec 9, 2020
    Posts:
    1
    Hello.
    I used your script and seemed to work, but the shadows are offset from the actual tiles. I don't know what is going on
    since I am new. Any help from anyone would be great :D.

    Here's a screenshot to show what I mean:

    Unity 2D shadows.png
     
  7. BrianCraig

    BrianCraig

    Joined:
    Apr 13, 2020
    Posts:
    6
    Hi! I could assist you! Do you have a way to share me the actual scene(git?)? From what i see it may be caused by some object transform. If you don't mind i could assist you also by Discord Brian#8296.
     
  8. unity_1A5EAB26E5FC36589A58

    unity_1A5EAB26E5FC36589A58

    Joined:
    Apr 6, 2021
    Posts:
    1
    So I've downloaded it and want to know, where should I add it? Somewhere under the library folder?

    Edit: I got it, just put it under assets. THANK YOU! This was super helpful!
     
    Last edited: Apr 21, 2021
  9. sRioni

    sRioni

    Joined:
    Apr 8, 2020
    Posts:
    12
    Hi, I've downloaded your project and it's so cool, but it turned out to be pretty inneficient in big and medium tilemaps as you are doing a getComponent in a update and also you are creating and destroying lots of Gameobjects. I've made some changes.

    First, in my tilemap your script generated like +200 GameObjects, so I've added a field to limit the number of shadows/GameObjects a tilemap can cast, this is per tilemap, it's not a static field.

    Then, at the start of the script (Awake) I create maxShadowNumber PathShadows, and as I create them I store them in a List, so you can access then without having to iterate the childs of the transform and call getComponent for every of them

    Then I've added a field to control how much the script updates per second, I actually update it 2 times per second.

    In every update, the script filters the closest "colliders" to the camera of all the compositecollider2d colliders, I store then in a List<List<Vector2>>. Then I iterate the PathShadows List and I Call path.SetSize with every List<Vector2> point of the List<Lists<Vector2>> points.

    As path shadows inherits from ShadowCaster2D, the shadow paths updates automatically, so you only create some shadow casters and updates them every some time. This way works much better.

    I've also fixed a little mistakei in getLayers method, propCount has to be increased in each iteration, not inside the if, so I just removed the field and used the iterator i variable instead.

    I'll do a pull Request to your repo so you can check the changes

    I also want to ask you if I could (or you) upload this as s free asset to the unity store. It's still kinda beta but I think it can be already used. It only becomes problematic when there are more than 64 shadow caster in total, but I think it's normal, at the end they are 64 GameObject with ShadowCasters2D, nothing to do there
     
  10. gaminggenghis

    gaminggenghis

    Joined:
    Mar 7, 2021
    Posts:
    1
    This worked great! I have no idea if this is just an individual case for me or a regular problem but I want to address it.

    If you make a "box" around your 2d light source they will not render to the walls of the world you will need to make a "hole" as an example. Bug1.PNG bug2.PNG
     
  11. Doggy88

    Doggy88

    Joined:
    Sep 8, 2019
    Posts:
    3
    Thank you very much for this!
     
  12. Dodoologist

    Dodoologist

    Joined:
    Aug 31, 2021
    Posts:
    1
    Thank you so much this was very helpful.
     
  13. Rakno

    Rakno

    Joined:
    Oct 18, 2021
    Posts:
    1
    This is amazing thank you, I've tried other solutions but yours has been the only one that updates the shadows during runtime at the point where a change was made. (working on a terraria-style mining game, so I needed the shadows to update as I destroyed block).

    Edit" I do have one recommendation. Destroying tiles dynamically in-game causes the screen to flash, as the current shadows are deleted before the new shadows are generated. I fixed this by storing the current shadows in a new list called Old shadows, generating the new shadows, THEN going back and destroying the old shadows within the list. I'm not nearly as experienced with coding as you are, so I'm sure you could implement this better then what I figured out in my own project, I would love to see this added.
     
    Last edited: Sep 15, 2022
  14. WMaC51

    WMaC51

    Joined:
    Dec 23, 2022
    Posts:
    2
    This is kind of off-topic but I'm gonna ask anyways:

    I'm new to the Unity Tilemap System and would like to know how you got it to automatically calculate the edges of each tile so you don't have to draw each individual one. This would be really helpful because drawing them individually is such a pain.
     
  15. AssassinSquid

    AssassinSquid

    Joined:
    Nov 5, 2020
    Posts:
    4
    I've run into an issue where the shadows are cast perfectly fine but if the tilemap makes a closed space around the light it goes completely dark. Is this something I can fix?

    edit: it only happens when self shadows is on, but when self shadows is off the lights shine through some tiles and not others
     
    Last edited: May 4, 2023