- Home /
How to use contact data from simultaneous collisions?
I have a ball that bounces the opposite way to a contact point (jumpPoint) when I press Jump.
The problem I am having is that if the ball has 2 contacts (either on the same object or on two separate objects), it only jumps away from the first contact point. Is there a way to calculate all contacts points with the ball from every object and work out the correct jump angle.
I have tried the 2 following methods: (all variables are vector2's. Most of the math here is done in Update rather than collision, I've just included it here to better show whats going on)
1:
void OnCollisionStay2D(Collision2D other)
{
ballPos = transform.position;
contact1 = other.contacts[0].point;
output = conact1 - ballPos;
jumpPoint = -output.normalized;
}
2:
void OnCollisionEnter2D(Collision2D other)
{
foreach (ContactPoint2D contact in other.contacts)
{
ballPos = transform.position;
contact1 = contact.point;
output = dir2 - dir1;
jumpPoint = -output.normalized;
}
Answer by Fritsl · May 14, 2017 at 07:58 PM
What do you do to add force? Because if you use physics, and just add all of it in fixedupdate, basically that should be it.
Else, maybe you can supply a little more info on the game and why you chose the setup you have?
Sorry for the late reply, my browsers were causing a lot of problems with unity answers.
The way I add force is fine, the script works in most situations, I have narrowed down the issue: The problem I am having is that if the ball is in contact with 2 separate colliders (as apposed 2 contact.points on the same collider), the script doesn't work, I believe that each different collision2D "other" is making a new instance, and I am unsure how to access the contact.points of the different instances. Here is my code (updated from last time):
void OnCollisionEnter2D(Collision2D other)
{
contactCount = other.contacts.Length;
if (contactCount == 1)
{
contactPos = other.contacts[0].normal;
}
else if (contactCount == 2)
{
contactPos = (other.contacts[0].normal + other.contacts[1].normal) / 2;
}
}
Really, I am looking to see if there is a way to access the second version of Collision2D other that is being made. I will count how many version of other there are, and average the contact.point normal provided by each version of other. I am unsure if this is the correct solution, but I have been testing it for days and this seems to be the problem. Thankyou for the reply to my original question.
Check out the Execution order of the Physics frame here: https://docs.unity3d.com/$$anonymous$$anual/ExecutionOrder.html
All collision calls are made before the next FixedUpate. What you could do, is have a List of Collision2Ds in which you collect all the collision calls from the OnCollision functions. Then, on the next FixedUpdate, you work through that list and then clear it.
Would that solve your problem?
Thankyou, I will give this a try. It is pretty strange that there isn't a simpler way to get all the contact info regardless of how many and which colliders are in contact with the ball.
The contact info of the ball in the inspector shows the exact data I need in a useful array, that would be perfect. Thanks for the reply.
I think there's something fundamentally wrong here: I'm not sure you'll get great results out of adding 2 normals and then divide by 2.
There's I$$anonymous$$O some strange things here, but it might be something you have thought about that I cannot see. But at least: You'll need to normalize your result after you have /2
$$anonymous$$aybe that'll fix it?
Under all circumstances I'd not do If 1, then this, if 2 then that, but always take everything and make that work ;)
Sorry, I should have said, the resulting vector is normalized. The problem I am having isn't in calculating the correct jump vector / direction. The problem I am having is in getting the contact.normals from each collision.other.
Each collider the ball collides with produces and array of contact points, to get the correct direction the jump force needs to be applied in, I just take the average of the contact.normals, and normalize. This method works fine for getting multiple contact.normals from the same collider. However, this method doesn't work in getting contact.normals from multiple colliders at the same time. Is there a way to access the contact.normal array of each all colliders the ball is in contact with. Thankyou for the reply :)
Answer by vProject · May 18, 2017 at 12:37 AM
TO: Fritsl
The site has been bugged for me for days I'm afraid, I can't reply to you directly Fritsl, but seem to be able to reply to the question as a whole, so I hope you see this.
The way I add force works fine:
myRigidBody.AddForce(jumpPoint * force, ForceMode2D.Impulse);
It's the calculation of the jump direction, jumpPoint, thats the problem. Is there a way to get the contact data of each instance of Collision2D other, because right now if the ball in contact with more than one instances of "other" it will choose one of them at random as the object to bounce off.
In addition to this, there are cases where the ball can have more than one contact point with a single object. I know this produces an array, but I am unsure how to use this array correctly. I feel like I need something like the following, but am unsure how to implement it correctly:
If (contact.point.amount = 1)
{
contact1 = other.contacts[0].point;
}
else if (contact.point.amount = 2)
{
contact1 = other.contacts[0].point + other.contacts[1].point;
}
I'm sorry but it's hard to get any much closer when not having the project to hammer ;)
Here's a couple of pointers - things you may or may not know, but the tools I'd look at, I would think:
A) If you have a 'Direction Vector' - as often the result of 'Normal', it is a normalized vector. If you have a transform position, and add the Direction Vector to that, you have .. a direction: Example Direction Vector: (0,1,0) Position: (0,0,0) Result: (0,1,0).
B) If you multiply your direction with 100, add it to position and draw a line from your position to that direction, you get a 100 units long line.
https://docs.unity3d.com/ScriptReference/Debug.DrawLine.html
Visualizing what is going on is key.
So I'd set up a visual indication of ALL the variables at stake: Red for [0], Blue for [1] Green for Calculated etc.
Then play game, and you will be able to see in Editor what all your variables are trying to do.
I hope that helps ;)
You have been a big help. I have sorted the problem now with a mix of help form you and DerDude. Thankyou very much.
Answer by Raptosauru5 · Apr 12, 2020 at 11:29 AM
vProject: Would you mind posting the solution you came up with please? This forum does not allow users to directly message each other (which I think is stupid, especially for the cases where the problem got solved but was not shared) Thanks in advance, if you read this
Your answer
Follow this Question
Related Questions
Jumping effectively in a 2D sidescroller 0 Answers
Using IgnoreLayerCollision and IgnoreCollision together 0 Answers
How can I allow the rope to correctly interact with Box and Polygon colliders? 0 Answers
Using OnTriggerEnter2D/OnTriggerExit2D with Time.timeScale set to 0 1 Answer
how to make a 2d colider script detector,how mto make a simple colision detect2d script 1 Answer