Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Destructible 2D ☄️ Dynamic Sprite Destruction

Discussion in 'Assets and Asset Store' started by Darkcoder, May 29, 2014.

  1. Toastbyte

    Toastbyte

    Joined:
    Sep 1, 2016
    Posts:
    51
    Hi there @Darkcoder

    I wanted to ask how to manually update the damaged alpha texture of a sprite shape. The Polygon2D colliders are up to date with how it should look like, but the texture is not:

    upload_2022-12-22_23-22-2.png

    Thanks in advance
     
  2. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,332
    The current destruction state is stored in the D2dDestructibleSprite component's AlphaData setting which is a 2D array of AlphaWidth * AlphaHeight size. If you manually modify this then you must call the NotifyRebuilt() method after, which will update the visual destruction texture, and colliders.
     
    Toastbyte likes this.
  3. Leyren

    Leyren

    Joined:
    Mar 23, 2016
    Posts:
    29
    Hey, thanks for the package, it's really helpful and offers a lot of features. One tiny thing I noticed with the D2dDestroyer:
    1. The shrinking logic is using the configured fade value instead of shrink value:
      Code (CSharp):
      1. finalScale *= Life / FadeDuration
    2. The shrinking is not clamped to a multiplier of 1. E.g. if Life = 1 and Shrinking (or currently Fading) duration is 0.1, it would start at a scale of 10. (On fading, it would wait for 0.9s before starting, but on shrink that's not the case)
     
  4. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,332
    Thanks for pointing this out, this will be fixed in the next version!
     
  5. Westy661

    Westy661

    Joined:
    Sep 13, 2015
    Posts:
    14
    Hello! Thanks for the cool asset, i like it very much.
    However i have a problem i hope you can help with :).

    So i have an arrow, which is a projectile in my game. It gets force applied to it, and in an
    OnCollisionEnter2D method i check for some internal gameplay code, and if the arrow didnt hit a player i call
    D2dFracturer.Fracture() on it.
    The problem is, that the fractures then hit something (via the OnCollusionEnter2D) again and again spawning countless number of other fractures, which slows the game down to a halt.

    So the question: Is there a way to exclude nested fractures (fractured parts fracturing). I know there is damage and multipliers, but im looking for a one liner for visual candy.

    Question2: What to do if i want to reuse the fractured asset? (Like a player which got a limb cut off). Do i have to manually disable the original object, instantiate the sprite representation, and fracture that?
     
    Last edited: Jan 6, 2023
  6. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,332
    1 - If your custom fracturing script is on your arrow, I'm not sure why each fractured part would then fracture each other. They don't have your script on, right? If it's the arrow that keeps hitting the fractured pieces, then you could check the destructible object's AlphaRatio value before fracturing (e.g. 1 means it hasn't been damaged yet, and lower values like 0.5 means it's half damaged).

    2 - I'm not sure I understand the question. Do you mean you want to prevent the player object/script/etc from being duplicated when it gets fractured or sliced (i.e. so you only ever have one player in your scene)? If so, you could use the fixture system and attach it to the head or somewhere, and put your player script on that. The fixture will only ever be attached to one destructible object even after splitting/fracture, so it can prevent duplication. Just keep in mind if you destroy the pixel the fixture is on, the fixture will be destroyed.
     
  7. Toastbyte

    Toastbyte

    Joined:
    Sep 1, 2016
    Posts:
    51
    Hello @Darkcoder
    Thanks for this incredible asset and your helpful answers in the forum!

    I have a very specific question. Hopefully you can help me.

    In the end of the Search() function of D2dSplitter.cs:
    I want to take all information from an island, add this information to another island (basically have 2 islands in 1) and finally delete the old island from the list.
    This is because later during TrySplit(), I don't want the old island to be split. Instead, the old island should be treated just like the first island in the islands[] list, which triggers "isLast = true" in SplitNext() of D2dDestructible.cs.

    Another way to explain this: I want specific islands to not be considered during the splitting process (as if splitting ) and came up with the idea of combining all the islands that should not be split into one "cluster" of islands. This cluster of islands -being in just one entry in the islands[] list- would then trigger the isLast = true boolean and not be considered during splitting.

    Here is what I tried doing, however it does not work as expected and I'm not sure if I'm completely missing something. I would really appreciate your input!!!

    Code (CSharp):
    1. //1. Scan for islands that should not be considered when splitting
    2. //(all islands marked as .isGround = true should not be considered when splitting)
    3.  
    4. //List that stores all indexes of the .isGround marked islands in islands[] list
    5. List<int> indexesOfMarkedIslands = new List<int>();
    6.  
    7. for(int i = 0; i < islands.Count; i++)
    8. {
    9.     if (islands[i].isGround)
    10.     {
    11.         indexesOfMarkedIslands.Add(i);
    12.     }
    13. }
    14.  
    15. //2. Add all information from the marked island to another island. Repeat for every marked island.
    16. //Here, I chose the first marked island as the "cluster" that should contain the information of all added islands: islands[indexesOfMarkedIslands[0]].
    17.  
    18. for (int i = 1; i < indexesOfMarkedIslands.Count; i++)
    19. {
    20.     for(int a = 0; a < islands[indexesOfMarkedIslands[i]].Lines.Count; a++)
    21.     {
    22.         islands[indexesOfMarkedIslands[0]]
    23.             .Lines.Add(islands[indexesOfMarkedIslands[i]].Lines[a]);
    24.     }
    25. }
    26.  
    27. //3. Finally, delete all islands that were transfered in step 2 to islands[indexesOfMarkedIslands[0]], since they are not needed anymore and should not be considered during the splitting process.
    28. for(int i = 1; i < indexesOfMarkedIslands.Count; i++)
    29. {
    30.     islands.Remove(islands[indexesOfMarkedIslands[i]]);
    31. }
    Or is there maybe a better way of ignoring certain islands during the splitting process?
     
    Last edited: Jan 7, 2023
  8. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,332
    Islands contain more than just the Lines list, you must also update the Count (pixel count), and MinX/MaxY/MinY/MaxY (pixel boundary) values, otherwise the split islands won't generate correctly.

    You can see lines 301-305 of D2dSplitter::Search for how this is done when adding new lines to an island.

    As long as the final island list has unique lines and the correct count + boundary then splitting should work with any kind of island modifications you perform.

    Also, keep in mind the order of the islands will be more or less scanline order, so combining the islands based on their list index may not be so useful. You might want to check their Count or boundary center or something, but it depends on what you're trying to do.
     
    Toastbyte likes this.
  9. elvin0272

    elvin0272

    Joined:
    Feb 16, 2021
    Posts:
    13
    Hello. I use D2DRequirements and Alpha Ratio from 0 to 1. For some reason, sometimes the method is called 2 times. I need to make the method called only 1 time. How can I do this?
     
  10. elvin0272

    elvin0272

    Joined:
    Feb 16, 2021
    Posts:
    13
    Hello @Darkcoder . Is this forum being checked? My deadlines are burning. I never figured it out. Where else can I write? Do you have a discord channel or telegram?
     
  11. elvin0272

    elvin0272

    Joined:
    Feb 16, 2021
    Posts:
    13
    My problem has not been solved. How can I turn to the event for cutting sprite and impose my method on it ONCE. Is this asset no longer supported?
     
  12. singlarijul24

    singlarijul24

    Joined:
    Jan 4, 2023
    Posts:
    1
    Hey! I just imported this asset and I am having issues with the d2d splitter thing. I want to slice the objects and i was just testing to see if simple slicing works with a sprite circle in my game scene, but for some reason it doesnt. The demo scene with the asset works fine, i created a new scene and tested it works fine.
    I added circle sprite and then made it d2d splitter component, added a drag to slice game object as well. is there anything i am missing?
     
  13. alahaboba

    alahaboba

    Joined:
    Dec 30, 2022
    Posts:
    2
    Hello, in order to heal sprite, it must be damaged first. How can I just make a sprite completely damaged when start the game. I read the comment about same problem, but it is in 2017, not sure that can help much. Many thanks
     
  14. jarbleswestlington_unity

    jarbleswestlington_unity

    Joined:
    Dec 6, 2017
    Posts:
    32
    I've run into a problem and was wondering if you had a suggestion. I have a project where all of a sudden the collider child of a gameobject with a d2d polygon is invisible, and clicking on the collider child freezes my editor with no error. I tried reimporting the d2d asset, but the project seems to still be corrupted. Any ideas?
     
  15. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,332
    Sorry for the late reply.

    The D2dRequirements component stores an internal 'met' value, which changes based on your requirement settings. If this met value changes to true then the OnRequirementsMet event is invoked. Since this met value is by default false, if your initial requirements are true, then when you start your game it will immediately fire the event. So perhaps this causes unexpected behavior in your game? If so, you can enable the inspector debug mode and enable met in edit mode. I can't see how it would get called twice though. You could add a breakpoint to the met value change code and debug it to see when and why it's changing.


    I'm not sure I understand the issue. If you can prepare a really simple demo scene and send it to me then I can test it.


    The heal feature heals toward the 'HealSnapshot' you specify, so you should configure your healed sprite first, make a snapshot of it, and then replace your D2dDestructibleSprite's Shape with a destroyed version of your sprite. Keep in mind the sprite must be the same size as the non-destroyed version so the heal snapshot resolution is the same.


    If it's just one object then can you rebuild it? If it's too complex then you could try turning it into a prefab and see if that fixes it. If not, maybe enabling the debug inspector or removing the inspector tab allows you to select it? If not, you could try putting it in an empty scene and deleting the child by manually editing the scene file with a text editor.
     
  16. alahaboba

    alahaboba

    Joined:
    Dec 30, 2022
    Posts:
    2
    why my destructible sprite dont have alpha count although it display normal on my game, i meant everything work perfectly like it can be damaged but the alpha count always 0 here is the image
     

    Attached Files:

  17. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,332
    Does this issue occur in the editor? Or only in a build? On a specific device?
     
  18. jarbleswestlington_unity

    jarbleswestlington_unity

    Joined:
    Dec 6, 2017
    Posts:
    32
    Is there any reason a d2d object is fracturing like this? With correct collisions but weirdly segmented and duplicate portions of its sprite? I changed very little from the shatter demo.

    upload_2023-4-28_15-2-48.png
     
  19. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,332
    Is your sprite part of an atlas? If so, could you try without an atlas? If not, could you send me a private message or email with a unitypackage of this sprite + a demo scene with it configured for destruction.
     
  20. jarbleswestlington_unity

    jarbleswestlington_unity

    Joined:
    Dec 6, 2017
    Posts:
    32
    Perfect, resolved. Last question: When an object fractures, is there a way to set its pivot closer to the center of the collision? The default pivot seems to be that of the original gameobject:
    upload_2023-5-1_10-54-37.png
     
    Darkcoder likes this.
  21. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,332
    It might be possible, but I'm out of town for the next week so I can't say for sure. I'll look into it after I get back.
     
  22. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,332
    I had a quick look into this and it seems like it would be fairly difficult to implement.

    In terms of physics this doesn't matter because Rigidbody2D objects rotate about their own pivot based on the colliders, so this would only matter for custom rotation or scaling, in which case you would have to do the same as the physics system and base your rotation/scaling on the center of the destructible object. You could directly read the Rigidbody2D's centerOfMass for this. If you don't have one then you can call your D2dDestructibleSprite component's AlphaToLocalMatrix.MultiplyPoint(new Vector2(0.5f, 0.5f)) method, where xy of the returned vector is the center in local space.
     
  23. jarbleswestlington_unity

    jarbleswestlington_unity

    Joined:
    Dec 6, 2017
    Posts:
    32
    So the reason I asked is that when I use torque on a rigidbody 2D, it seems each fractured piece will simulate rotating around the pivot. Is this unusual behavior, and/or do you happen to have any suggestions as to a fix?

     
  24. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,332
    Sorry for the late reply.

    I've attached a demo scene showing that Rigidbody2D torque is applied to the center of mass, so it doesn't matter where the pivot point is. Just click the object to fracture it, and you will see each part rotates around its center, even though all objects have the same actual pivot.

    Not sure what's going on in your video. Do you have some kind of custom rotation script that uses the Transform's rotation? If so, you must use the Rigidbody2D's centerOfMass to both translate and rotate your object around this axis rather than relying on the Transform's origin.
     

    Attached Files:

  25. jarbleswestlington_unity

    jarbleswestlington_unity

    Joined:
    Dec 6, 2017
    Posts:
    32
    Nope, just a simple add torque 2D impulse. I have a splitter and a fracturer attached. It looks like the center of mass of each piece is being set incorrectly somehow. When I manually the center of mass to the bounds center of the collider2D, it is still incorrect somehow. I'm going to keep testing things
     
    Last edited: Jun 14, 2023
  26. Humusk

    Humusk

    Joined:
    Jan 8, 2021
    Posts:
    4
    Hi!

    I want to buy the asset but I have a question first about how splitting objects work.

    In the documentation it says:

    When a destructible sprite splits in half using the D2dSplitter component, it will be cloned/instantiated to make the other side, and D2dSplitter will automatically separate the destruction data between the two destructible sprites.

    My question is about how the data is separated, specially the mass of objects. If I split an object in half is the mass going to be half for each object?

    I need that to happen to be able to correctly implement the mechanic I want.

    Thanks!
     
  27. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    3,332
    If your destructible object uses the D2dPolygonCollider component and your Rigidbody2D has UseAutoMass enabled, then all separated parts will be given mass based on the area of the colliders. If you don't enable UseAutoMass, then you can add the D2dCalculateMass component, which will override the Rigidbody2D Mass setting based on the amount of solid pixels remaining in the current part of the destructible object.
     
  28. TibiTibith

    TibiTibith

    Joined:
    Mar 8, 2015
    Posts:
    29
    Just wanted to say this asset is incredible and that I've fixed the issues I've been telling you about in the emails, Carlos (I was incorrectly creating a sprite from a texture with wrong default settings and assigning it to my Shape and then firing Rebuild().) All good now!


     
  29. kentaruu97

    kentaruu97

    Joined:
    Nov 15, 2022
    Posts:
    1
    Hi @Darkcoder, I created a game using this package and used the D2D Repeat Stamp Object to destroy the target Object. It worked perfectly on normal Android devices, except the Samsung Galaxy A14, it's very laggy and has a dropped framerate. I tried to optimize the object as much as I could, with the Adaptive Performance Android package installed, but it's not helping at all.
    Can you find me away to fix this problem?