Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking solid objects in half #42

Open
MadCowChicken opened this issue Apr 1, 2022 · 6 comments
Open

Breaking solid objects in half #42

MadCowChicken opened this issue Apr 1, 2022 · 6 comments
Labels
documentation Improvements or additions to documentation

Comments

@MadCowChicken
Copy link

MadCowChicken commented Apr 1, 2022

Description

This isn't actually an issue, I'm just looking for guidance.

Suppose I have a rectangle (representing a brick) and a circle (representing a slow-ish bullet) and if the bullet hits the brick with enough speed I want to turn the brick from one object into two or three objects along fracture lines that seem intuitive.

Do you think it would work for me to modify the ContactManager.Collide() method in such a way that it does two passes... The first pass could replace the bottom part of the function that looks like

// Here we destroy contacts that cease to overlap in the broad-phase.
if (overlap == false)
{
    Contact cNuke = c;
    c = cNuke.GetNext();
    Destroy(cNuke);
    continue;
}

// The contact persists.
c.Update(m_contactListener);
c = c.GetNext();

with something like

if (overlap == true)
{
    ...break brick into pieces if conditions are met...
}

and then the second pass would be exactly the code that's in the ContactManager.Collide() method normally?

Or would this not work? Maybe I would need to rewind positions after the first pass? Possibly by capturing the world state at the beginning of the first pass and resetting it to that (except for the broken brick) before doing the second pass?

@MadCowChicken MadCowChicken added the documentation Improvements or additions to documentation label Apr 1, 2022
@thomasvt
Copy link
Collaborator

thomasvt commented Apr 1, 2022

Hello,

Splitting a brick into pieces is game logic, and not the job of the physics system (box2d). The job of the physics system is to simulate interaction of physical bodies that the game logic defined earlier. The Physics engine should not be used to decide when to change or create new bodies based on game-specific rules like the one you are describing.

Therefore I suggest you do not change any internal code of box2d, but to use box2d's ContactListener (many tutorials online. eg. https://www.iforce2d.net/b2dtut/collision-callbacks (should be trivial to translate to C# equivalent).

Your ContactListener implementation will receive collision notifications from box2d. You can then check if one body is a bullet and the other body is a brick. Splitting the brick will work best by deleting the brick entirely and creating several new brickfragments as separate game objects (each with their own RigidBody).

By the way:
This kind of question is more a working-with-box2d question, or even general gamedev question. You will reach a lot more people by asking things like this through eg. StackOverflow. The original box2d is C++, so many people will respond from that C++ perspective, but the box2d concepts translate perfectly to C# with Box2d-netstandard. So, you should be able to get help from them too.

@codingben
Copy link
Owner

I agree with @thomasvt. @MadCowChicken Feel free to see examples how to use ContactFilter in related issue.

@MadCowChicken
Copy link
Author

I didn't know it had ContactListener / ContactFilter sort of support. Thank you.

@MadCowChicken
Copy link
Author

Actually a quick look at the collision callbacks link above makes me believe it is not what I'm looking for. I don't need to add code to run after a collision is processed. I need to add code to run before a collision is processed.

I need to split a brick the moment before the bullet hits the brick so that the pieces can fly apart more naturally.

@thomasvt
Copy link
Collaborator

thomasvt commented Apr 1, 2022

So, you want the ball to hit the brick, break it and have the same impact velocity propagate realistically to the broken pieces?

I don't think you can create that without faking some things here and there. Some ideas:

  • Set the pieces' velocity to something you calculate yourself: you could take the relative impact location into account per piece.
  • You could break up the brick and then set the bullet velocity to hit them again.
  • You could also add a thin "skin" sensor around your bullet (add a second, slightly larger fixture with IsSensor = true to the bullet's RigidBody) to detect a collision just before it actually happens (worth a try, but I think this will not work well in practice, you will at least have to set IsBullet true so box2d does CCD)

@MadCowChicken
Copy link
Author

If I create a copy of the bullet with IsSensor = true and fix it to the original, is there a way to guarantee that the sensor collisions will happen before the bullet collisions? And also allow my dynamic fracturing code to be run before the bullet collisions, rather than running my dynamic fracturing code at the end of the collision process?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

3 participants