Search Unity

Script for generating ShadowCaster2Ds for Tilemaps

Discussion in '2D' started by AlexVillalba, Jun 6, 2020.

  1. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Hi everybody,

    Since I did not find any built-in functionality to make shadow casters fit in the shape of the tilemaps (something that I think it is fundamental) I made my own script to achieve such thing without having to manually create and adjust every shadow caster.

    Just add the script to your project and you will see a new option in the top menu of the editor. Once you execute it, shadow casters will be created for all the tilemaps in the open scene. It requires that the tilemaps have CompositeCollider2Ds. I made it as generic as possible so it is not limited to tilemaps, it only depends on composite colliders.

    I hope it helps you to save some time.

    I re-posted this on my website: https://www.jailbrokengame.com/2023/05/08/script-for-generating-shadowcaster2ds-for-tilemaps-repost/

    Other code I shared:
    Pixel perfect LineRenderer2D
    Delaunay Triangulation with constrained edges
    Target sorting layers as assets

    Regards.



    Code (CSharp):
    1. // Copyright 2020 Alejandro Villalba Avila
    2. //
    3. // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
    4. // to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
    5. // and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    6. //
    7. // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    8. //
    9. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    10. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    11. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    12. // IN THE SOFTWARE.
    13.  
    14. using System.Collections.Generic;
    15. using System.Reflection;
    16. using UnityEngine;
    17. using UnityEngine.Experimental.Rendering.Universal;
    18.  
    19. /// <summary>
    20. /// It extends the ShadowCaster2D class in order to be able to modify some private data members.
    21. /// </summary>
    22. public static class ShadowCaster2DExtensions
    23. {
    24.     /// <summary>
    25.     /// Replaces the path that defines the shape of the shadow caster.
    26.     /// </summary>
    27.     /// <remarks>
    28.     /// Calling this method will change the shape but not the mesh of the shadow caster. Call SetPathHash afterwards.
    29.     /// </remarks>
    30.     /// <param name="shadowCaster">The object to modify.</param>
    31.     /// <param name="path">The new path to define the shape of the shadow caster.</param>
    32.     public static void SetPath(this ShadowCaster2D shadowCaster, Vector3[] path)
    33.     {
    34.         FieldInfo shapeField = typeof(ShadowCaster2D).GetField("m_ShapePath",
    35.                                                                BindingFlags.NonPublic |
    36.                                                                BindingFlags.Instance);
    37.         shapeField.SetValue(shadowCaster, path);
    38.     }
    39.  
    40.     /// <summary>
    41.     /// Replaces the hash key of the shadow caster, which produces an internal data rebuild.
    42.     /// </summary>
    43.     /// <remarks>
    44.     /// A change in the shape of the shadow caster will not block the light, it has to be rebuilt using this function.
    45.     /// </remarks>
    46.     /// <param name="shadowCaster">The object to modify.</param>
    47.     /// <param name="hash">The new hash key to store. It must be different from the previous key to produce the rebuild. You can use a random number.</param>
    48.     public static void SetPathHash(this ShadowCaster2D shadowCaster, int hash)
    49.     {
    50.         FieldInfo hashField = typeof(ShadowCaster2D).GetField("m_ShapePathHash",
    51.                                                               BindingFlags.NonPublic |
    52.                                                               BindingFlags.Instance);
    53.         hashField.SetValue(shadowCaster, hash);
    54.     }
    55. }
    56.  
    57. /// <summary>
    58. /// It provides a way to automatically generate shadow casters that cover the shapes of composite colliders.
    59. /// </summary>
    60. /// <remarks>
    61. /// Specially recommended for tilemaps, as there is no built-in tool that does this job at the moment.
    62. /// </remarks>
    63. public class ShadowCaster2DGenerator
    64. {
    65.  
    66. #if UNITY_EDITOR
    67.  
    68.     [UnityEditor.MenuItem("Generate Shadow Casters", menuItem = "Tools/Generate Shadow Casters")]
    69.     public static void GenerateShadowCasters()
    70.     {
    71.         CompositeCollider2D[] colliders = GameObject.FindObjectsOfType<CompositeCollider2D>();
    72.  
    73.         for(int i = 0; i < colliders.Length; ++i)
    74.         {
    75.             GenerateTilemapShadowCastersInEditor(colliders[i], false);
    76.         }
    77.     }
    78.  
    79.     [UnityEditor.MenuItem("Generate Shadow Casters (Self Shadows)", menuItem = "Tools/Generate Shadow Casters (Self Shadows)")]
    80.     public static void GenerateShadowCastersSelfShadows()
    81.     {
    82.         CompositeCollider2D[] colliders = GameObject.FindObjectsOfType<CompositeCollider2D>();
    83.  
    84.         for (int i = 0; i < colliders.Length; ++i)
    85.         {
    86.             GenerateTilemapShadowCastersInEditor(colliders[i], true);
    87.         }
    88.     }
    89.  
    90.     /// <summary>
    91.     /// Given a Composite Collider 2D, it replaces existing Shadow Caster 2Ds (children) with new Shadow Caster 2D objects whose
    92.     /// shapes coincide with the paths of the collider.
    93.     /// </summary>
    94.     /// <remarks>
    95.     /// It is recommended that the object that contains the collider component has a Composite Shadow Caster 2D too.
    96.     /// It is recommended to call this method in editor only.
    97.     /// </remarks>
    98.     /// <param name="collider">The collider which will be the parent of the new shadow casters.</param>
    99.     /// <param name="selfShadows">Whether the shadow casters will have the Self Shadows option enabled..</param>
    100.     public static void GenerateTilemapShadowCastersInEditor(CompositeCollider2D collider, bool selfShadows)
    101.     {
    102.         GenerateTilemapShadowCasters(collider, selfShadows);
    103.  
    104.         UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
    105.     }
    106.  
    107. #endif
    108.  
    109.     /// <summary>
    110.     /// Given a Composite Collider 2D, it replaces existing Shadow Caster 2Ds (children) with new Shadow Caster 2D objects whose
    111.     /// shapes coincide with the paths of the collider.
    112.     /// </summary>
    113.     /// <remarks>
    114.     /// It is recommended that the object that contains the collider component has a Composite Shadow Caster 2D too.
    115.     /// It is recommended to call this method in editor only.
    116.     /// </remarks>
    117.     /// <param name="collider">The collider which will be the parent of the new shadow casters.</param>
    118.     /// <param name="selfShadows">Whether the shadow casters will have the Self Shadows option enabled..</param>
    119.     public static void GenerateTilemapShadowCasters(CompositeCollider2D collider, bool selfShadows)
    120.     {
    121.         // First, it destroys the existing shadow casters
    122.         ShadowCaster2D[] existingShadowCasters = collider.GetComponentsInChildren<ShadowCaster2D>();
    123.  
    124.         for (int i = 0; i < existingShadowCasters.Length; ++i)
    125.         {
    126.             if(existingShadowCasters[i].transform.parent != collider.transform)
    127.             {
    128.                 continue;
    129.             }
    130.  
    131.             GameObject.DestroyImmediate(existingShadowCasters[i].gameObject);
    132.         }
    133.  
    134.         // Then it creates the new shadow casters, based on the paths of the composite collider
    135.         int pathCount = collider.pathCount;
    136.         List<Vector2> pointsInPath = new List<Vector2>();
    137.         List<Vector3> pointsInPath3D = new List<Vector3>();
    138.  
    139.         for (int i = 0; i < pathCount; ++i)
    140.         {
    141.             collider.GetPath(i, pointsInPath);
    142.  
    143.             GameObject newShadowCaster = new GameObject("ShadowCaster2D");
    144.             newShadowCaster.isStatic = true;
    145.             newShadowCaster.transform.SetParent(collider.transform, false);
    146.  
    147.             for(int j = 0; j < pointsInPath.Count; ++j)
    148.             {
    149.                 pointsInPath3D.Add(pointsInPath[j]);
    150.             }
    151.  
    152.             ShadowCaster2D component = newShadowCaster.AddComponent<ShadowCaster2D>();
    153.             component.SetPath(pointsInPath3D.ToArray());
    154.             component.SetPathHash(Random.Range(int.MinValue, int.MaxValue)); // The hashing function GetShapePathHash could be copied from the LightUtility class
    155.             component.selfShadows = selfShadows;
    156.             component.Update();
    157.  
    158.             pointsInPath.Clear();
    159.             pointsInPath3D.Clear();
    160.         }
    161.     }
    162. }
    163.  
    164.  
    If you want to generate it in runtime, on Awake, for a specific object:
    Code (CSharp):
    1. // Copyright 2021 Alejandro Villalba Avila
    2. //
    3. // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
    4. // to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
    5. // and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
    6. //
    7. // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
    8. //
    9. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    10. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    11. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    12. // IN THE SOFTWARE.
    13.  
    14. using UnityEngine;
    15. using UnityEngine.Experimental.Rendering.Universal;
    16.  
    17. namespace Game.Utils
    18. {
    19.     /// <summary>
    20.     /// Generates ShadowCaster2Ds for every continuous block of a tilemap on Awake, applying some settings.
    21.     /// </summary>
    22.     public class TilemapShadowCaster2D : MonoBehaviour
    23.     {
    24.         [SerializeField]
    25.         protected CompositeCollider2D m_TilemapCollider;
    26.  
    27.         [SerializeField]
    28.         protected bool m_SelfShadows = true;
    29.  
    30.         protected virtual void Reset()
    31.         {
    32.             m_TilemapCollider = GetComponent<CompositeCollider2D>();
    33.         }
    34.  
    35.         protected virtual void Awake()
    36.         {
    37.             ShadowCaster2DGenerator.GenerateTilemapShadowCasters(m_TilemapCollider, m_SelfShadows);
    38.         }
    39.     }
    40. }
    If you need extra help to make it work in your project, you can read this instructions written by the user unity_23B1DCF752DC46F6F768
    https://forum.unity.com/threads/scr...er2ds-for-tilemaps.906767/page-2#post-8712126
     
    Last edited: May 20, 2023
  2. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,514
    MD_Reptile likes this.
  3. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Regarding performance, it only creates a GameObject with a ShaderCaster2D component per independent block (i.e. non-continuous block) of the Tilemap. For example, in the image, it creates 14 objects. I don't know how the shadow casting system performs as the number of shadow casters increase, that's my only doubt and nobody can do anything to solve that (apart from Unity guys). Besides, I don't know if having a CompositeShadowCaster2D makes a difference or not in terms of performance.
     
    Redninja7002 likes this.
  4. japhib

    japhib

    Joined:
    May 26, 2017
    Posts:
    65
    Wow, this is awesome!
     
  5. Kashlavor

    Kashlavor

    Joined:
    Jan 10, 2014
    Posts:
    2
    Looks great, thank you.
     
  6. FarGalaxy

    FarGalaxy

    Joined:
    Jun 24, 2019
    Posts:
    1
    Hi, the script works fine, but an error occurs when building the project, because Unity tries to add this script with UnityEditor to the build.

    I solved this problem by adding the
    #if UNITY_EDITOR
    at the beginning and
    #endif
    at the end of the script.
     
  7. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Sorry I forgot to add the compiler definitions. I've updated the script.
     
    thathurtabit likes this.
  8. Dannyxv8

    Dannyxv8

    Joined:
    Jun 29, 2020
    Posts:
    1
    Wow, this actually worked unlike everything else I've tried so far! You're a god!! I just hope there's not too many side effects or performance intensive...
     
  9. PaulKhill

    PaulKhill

    Joined:
    Jul 30, 2020
    Posts:
    15
    Quick addition for anyone trying to make this work : if you are using a Tilemap Collider 2D, you must add a Composite Collider 2D and check the "Used by Composite" option in the Tilemap Collider 2D for this to work. (You may also want to set the bodytype of the rigid body to static, if you don't want your whole tilemap to fly)

    Great work friend !
     
  10. Mazemace

    Mazemace

    Joined:
    Jan 4, 2013
    Posts:
    7
    Looks great!

    The light travelled through walls for me, so I added the following code

    Code (CSharp):
    1. component.selfShadows = true;
     
  11. SurefireMille

    SurefireMille

    Joined:
    Nov 9, 2020
    Posts:
    1
    Hello,
    I can't seem to find the option that is supposed to execute. Could you send a screenshot or describe more specifically to me where I can find it? Sorry for this dumb question.

    Edit:
    I found it. It's just me who had not searched properly. If someone else has the same issue that I had, here is how to access it.

    Tools -> Generate Shadow Casters

    Yep, it's that simple.
    Again, sorry for this question.
     
    Last edited: Nov 9, 2020
    Subnormal and japhib like this.
  12. Amane224

    Amane224

    Joined:
    May 4, 2016
    Posts:
    6
    Great! Thank you for the useful script.
     
  13. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Added the line "UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();". Sometimes I just open the scene and generate the shadow casters, without making any other change. Since the editor does not realize about those changes, they are not saved. Pressing the Play button makes the scene restore its original content, as if nothing happened. Now the scenes are marked as dirty and everything works as expected.
     
  14. mega8200

    mega8200

    Joined:
    Aug 18, 2020
    Posts:
    1
    Hello, does the script work on runtime
     
  15. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Never tried.
     
  16. japhib

    japhib

    Joined:
    May 26, 2017
    Posts:
    65
    I'm pretty sure I got it to work at runtime in the past. You just have to remove anything that uses a "UnityEditor" namespace, like this line at the bottom:

    Code (CSharp):
    1. UnityEditor.SceneManagement.EditorSceneManager.MarkAllScenesDirty();
     
  17. LordHobbas

    LordHobbas

    Joined:
    Dec 10, 2018
    Posts:
    3
    Hi!

    I can't seem to get this to work.
    If I understand correctly, all I need to do is
    1. Import Universal RP from Package Manager.
    2. Copy paste the script to somewhere in my project
    3. Create a Tilemap, (and edit the collisions of course).
    4. Add a Tilemap Collider 2D and Composite Collider 2D to the Tilemap. (Make sure to check "Used By Composite" under TileMap Collider 2D).
    5. Lastly, run Tools > Generate Shadow Casters.

    Nothing changes after running it. I tested creating a new project for this but it made no difference.
    I'm running Unity 2020.2.4f1

    Is there anything obvious I'm missing?
     
  18. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Hi LordHobbas, let's try to find the issue. I'm not sure but could it be related to the Geometry Type in the CompositeCollider2D?
     
  19. LordHobbas

    LordHobbas

    Joined:
    Dec 10, 2018
    Posts:
    3
    Thanks for the quick response, I didn't expect that!
    It's set to "Outlines".
    I can see now that there are several "ShadowCaster2D" created as children to the Tilemap object, and they're recreated everytime I run the script. So the script seems to work perfectly. I think I've missed something else.
    Do I need to enable something to make the Tilemap receive shadows as well?
     
  20. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    You are welcome. If the shadow casters have the correct shape, then it all depends on the layers that are affected by the casters and the settings of the light, shadow intensity, target sorting layers, etc.
     
  21. LordHobbas

    LordHobbas

    Joined:
    Dec 10, 2018
    Posts:
    3
    I got it to work!
    I had to create a new Material. The one I already had was created before I set the custom pipeline asset as my graphics, and Unity did not like that. After creating a new one, and upping the shadow intensity on the lights, it started working perfectly!
     
    AlexVillalba likes this.
  22. Mindjar

    Mindjar

    Joined:
    Aug 13, 2013
    Posts:
    29
    Thanks for the script, works perfectly!
     
    AlexVillalba likes this.
  23. hkplay

    hkplay

    Joined:
    Jan 4, 2021
    Posts:
    12
    Hi, I would like to report a bug. Basically this will never work if the tilemap is a complete square, much like this

    upload_2021-5-17_21-56-41.png

    If the brown parts are walls, lights within the walls can never be seen. This was a big problem for me that I did not realise because literally my whole map was enclosed in one big square of walls.

    Right now I found out that removing ANY tile to break the wall will result in the shadow casters working properly. I do not think there is a workaround for this from the script as the paths are identical to the composite colliders, and I do not think we can adjust the composite colliders.

    One potential fix, which I may attempt, is to do a preprocessing before the game starts to try and break up such squares by placing it in a different tilemap. not completely sure of it yet though.

    EDIT: Example below:
    upload_2021-5-17_22-27-36.png
    There is a light source inside but it is not working because the whole shape is treated as one big shadow caster.
     
    Last edited: May 17, 2021
  24. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Hi hkplay, thank you for your report. I cannot think of a solution right now but, as an idea for now, do you really need the exterior walls to cast shadows? Are those shadows projected somewhere? Would it be possible that you put the perimeter in a different tilemap without shadow casters?
     
  25. Ziberian

    Ziberian

    Joined:
    Jan 9, 2018
    Posts:
    66
    Hello ThundThund,

    First of all I want to thank you for all the work you have done for the tilemap shadows! You are a champion, this was exactly what I was looking for.

    Currently I am having an issue that I do not know how to describe, if I have just a single block, or two blocks the shadows look fine... but I am generating random patterns of walls (using composite collider on those walls), but for some reason there are many shadows being casted? It looks really odd. I have attached a short gif of my player moving around (to really see how the shadows move), and also a picture with no shadows.

    P.S: The ONLY light in the scene is a point light centered around the player (Why are there these random shadows that look like there is a light coming from the corners of the map?)

    short video of my character moving around:
     

    Attached Files:

  26. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Thank you, I'm glad it's being useful for many people.
    Could you please share a capture of what shape do the ShadowCaster2Ds attached to the tilemap have?
     
  27. Ziberian

    Ziberian

    Joined:
    Jan 9, 2018
    Posts:
    66
    When I highlight the 2nd shadowcaster object it looks like it perfectly outlines the walls, attached images below...

    EDIT: Oh, also figured out how to disable the renderer. I will post a 4th image where you can see the outline much more clearly.

    EDIT 2: I think I have found the problem. There are walls all around the player that close up the whole area. If I remove those walls the shadows work perfectly, I think this is the same issue another user posted here on this post.

    EDIT 3: Confirmed that if I remove a single block from the outer wall the shadows work perfectly.
     

    Attached Files:

    • 1.png
      1.png
      File size:
      50 KB
      Views:
      381
    • 2.png
      2.png
      File size:
      49.6 KB
      Views:
      395
    • 3.png
      3.png
      File size:
      53.8 KB
      Views:
      376
    • 4.png
      4.png
      File size:
      40.7 KB
      Views:
      362
    Last edited: Jun 8, 2021
  28. Ziberian

    Ziberian

    Joined:
    Jan 9, 2018
    Posts:
    66
    Hello, have you ever found a solution to this issue? I am having the same problem.
     
  29. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Ah ok, so you have a closed tilemap. That's a known issue. I haven't worked on a solution yet.
     
  30. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    The problem is that the closed shapes that the composite collider generates in, for example, a ring-shaped tilemap, are 2 overlapping convex meshes that enclose the point light.
    The black area is the part where the light passes the stencil test.

    upload_2021-6-9_2-22-46.png

    upload_2021-6-9_2-24-4.png
     
  31. Ziberian

    Ziberian

    Joined:
    Jan 9, 2018
    Posts:
    66
    I think for now the solution I will do is destroy a single piece of wall from the corner, generate the shadows, and then place the tile back through the script. Thanks for the update though!
     
  32. Ziberian

    Ziberian

    Joined:
    Jan 9, 2018
    Posts:
    66
    Hello again ThundThund,

    I had a quick question, I have been trying for a very long time to do this but I can't. How can I call the method that is called when you press the button in the editor: Tools -> Generate Shadow Casters. I basically want to be able to do this through a script.

    If you were to generate the shadows through another script, how would you do that? Could you write a short example.

    Thanks in advanced!
     
  33. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    I've added the implementation of a component to the main post.
    It includes a small improvement in the shadow caster generator code, the line "component.Update();" which forces it to update the mesh of the shadow caster immediately.
     
  34. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    I also modified the #if UNITY_EDITOR blocks in the shadow caster generator.
     
  35. TheNightglow

    TheNightglow

    Joined:
    Oct 1, 2018
    Posts:
    201
    I think you have a bug in the current version of the code:
    you are calling GenerateTilemapShadowCasters as if it has a CompositeCollider2D and a bool parameter but you only define it on just a CompositeCollider2D parameter

    see line 118:
    Code (CSharp):
    1. public static void GenerateTilemapShadowCasters(CompositeCollider2D collider)
    and lines 102, 86 and 75
    Code (CSharp):
    1. GenerateTilemapShadowCasters(collider, selfShadows);
    Code (CSharp):
    1. GenerateTilemapShadowCastersInEditor(colliders[i], true);
    Code (CSharp):
    1. GenerateTilemapShadowCastersInEditor(colliders[i], false);
     
  36. millibar

    millibar

    Joined:
    Aug 3, 2015
    Posts:
    8
    HI
    It's say
    MissingReferenceException: The object of type 'CompositeCollider2D' has been destroyed but you are still trying to access it.
    and disappearance gameobject in Hierarch.
    why?
    Tilemap has Tilemap Collider 2D and Composite Collider 2D.
     
  37. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Thank you! I knew this was going to happen as I'm modifying the code in the post, without compiling (my copy of the code is different and cannot just copy and paste, I have to remove and change things). I hope it's correct now.
     
  38. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Could you post the line?
     
  39. millibar

    millibar

    Joined:
    Aug 3, 2015
    Posts:
    8
    Thanks for your responses

    MissingReferenceException: The object of type 'CompositeCollider2D' has been destroyed but you are still trying to access it.
    Your script should either check if it is null or you should not destroy the object.
    ShadowCaster2DGenerator.GenerateTilemapShadowCasters (UnityEngine.CompositeCollider2D collider, System.Boolean selfShadows) (at Assets/Scripts/ShadowCaster2DExtensions.cs:130)
    ShadowCaster2DGenerator.GenerateTilemapShadowCastersInEditor (UnityEngine.CompositeCollider2D collider, System.Boolean selfShadows) (at Assets/Scripts/ShadowCaster2DExtensions.cs:102)
    ShadowCaster2DGenerator.GenerateShadowCasters () (at Assets/Scripts/ShadowCaster2DExtensions.cs:75)
     
  40. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Do you have a shadow caster in the same object where the TilemapShadowCaster2D is?
     
  41. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    I've just added a check to the first loop of the GenerateTilemapShadowCasters method.
     
  42. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,500
    At least in 2021.2 you'll be able to read the actual primitive shapes/geometry produced from any Collider2D in a super efficient way. This might help for future versions.
     
  43. millibar

    millibar

    Joined:
    Aug 3, 2015
    Posts:
    8
    Is this correct?
     

    Attached Files:

  44. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    No. That object should not have a shadow caster. Anyway, with my last changes you should not have problems anymore.
     
  45. millibar

    millibar

    Joined:
    Aug 3, 2015
    Posts:
    8
    It worked. I understand how to use it, thank you
     
    AlexVillalba likes this.
  46. TheNightglow

    TheNightglow

    Joined:
    Oct 1, 2018
    Posts:
    201
    Not too important but now its missing the last closing } of the class in the end ;)
     
  47. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    Ooops! Fixed. Thank you.
     
  48. deku376

    deku376

    Joined:
    May 9, 2021
    Posts:
    1
    Thank you soo much your a life saver I've literally been up all night/ morning and you just helped i can finally get some sleep. Thank you sooooo much.
     
  49. AlexVillalba

    AlexVillalba

    Joined:
    Feb 7, 2017
    Posts:
    346
    I'm glad to read that, sleeping is important! Specially if you dream in code :D
     
  50. LoneXUnity

    LoneXUnity

    Joined:
    Mar 24, 2020
    Posts:
    7
    Dude I'm working on a project with softbodies and I used only the setpath method and setHash method, to change the shadow cast shape according to the softbody.
    and it worked like a charm, honestly I'm very thankful. you're great !