- Home /
Distance-based collision detection not accurate
I'm making a pretty simple mobile 2D puzzle game that requires a lot of collision detection between perfect circles. I had figured this would let me skip physics altogether, as they tend to bog down mobile projects, and detecting collisions between circles shouldn't be difficult to accomplish without it.
Basically the user is able drag a circle around the screen via touch. At certain time intervals, a disc (also perfectly circular) is spawned and shot across the screen; when the user-controlled circle comes in contact with the disc, the disc sticks to the circle and becomes a part of it (basically, the disc is parented to the circle). Not complicated.
In my update function I'm checking the distance between the spawned disc and the closest child of the user-controlled object, all of which are circles. Here's what it looks like:
var closest : float = 999;
var circ : Transform;
// Check for collision with main or children of main
for (var circle : Transform in main)
{
// Get the distance from this child object to the child
var nextDist = Vector3.Distance (circle.position, transform.position);
// If it is closer than the previous one, update closest circle
if (nextDist < closest)
{
closest = nextDist;
circ = circle;
}
// If the circle and the closest transform overlap...
if (closest <= ((transform.localScale.x / 2) + (circ.localScale.x / 2)))
{
// Stop movement and parent the circle to the main
EndLife ();
}
}
It works pretty well, but there's a problem - when the user moves the main object too fast, the collision detection seems to "lag", meaning discs won't detect a collision until they're partly inside an object. If the player moves the main object REALLY fast, sometimes discs won't detect anything at all and will just phase through the object, as if they never collided.
Is there a way around this? How is it possible that a distance check in the Update loop can be "slower" than the movement of an object that is also controlled through the Update loop? I feel like I'm misunderstanding something pretty fundamental here.
Any help would be greatly appreciated!
it looks like the last clause should be outside the loop, rather than inside it. did you make a typo? i think you've just accidentally put it in the wrong place
Just FWIW ...... "as they tend to bog down mobile projects" .. PhysX is incredibly fast, probably faster than anything one can write by hand. and it's hard to see that physics bogs down "mobile projects" as what 50% (80%? more?) of ifone games use physics
Yeah, it is outside the loop, I guess I just somehow copied it wrong.
And physics absolutely adds significant overhead to a project, mobile or not. It probably wouldn't be too big of a deal here, as the project is relatively small-scale, but it's always good to be as efficient as possible. It's entirely possible I'm being dumb with this particular problem though - I just can't wrap my head around why the distance check seems to not work at high speeds.
Just FWIW
"it's always good to be as efficient as possible"
The central thrust of all modern computing is that you engineer for reliability and ease of development.
You often hear the saying "don't optimize early."
"physics absolutely adds significant overhead to a project"
The resources usage added by PhysX is $$anonymous$$uscule compared to many (two dozen? four dozens?) other systems that grind away constantly in the modern hardware/software assembly.
To make an extreme analogy, it would be like program$$anonymous$$g for $$anonymous$$ac and saying, oh, I don't want to to use these lame systems Cocoa supplies for rendering type on a monitor, I will calculate the antialiasing myself in my own code.
Answer by Bunny83 · Sep 27, 2012 at 09:30 PM
Well, keep in mind objects don't really "move". They always jump to their next position. The movement "speed" and the framerate determine how much the object will "jump" each frame.
For example, when you have a monitor 1600 pixel wide and you move your mouse quickly from the left side to the right side, the cursor won't pass each of the 1600 pixels. It will probably stop / e visible at 5 to 30 positions in between even when it's 30 that means each "update" the cursor moved ~50 pixels.
To prevent those big jumps you can increase the sample rate, so you would move the objects several times in one Update step to reach the new position. This will decrease the move step size. This is sometimes called oversampling or interpolation. However this requires a lot more cpu power.
The second solution is to calculate the trajectory of the two objects and calculate if and where they meet. It's the search for the closest point of aproach. All those solutions are quite heavy to calculate.
The best fix is probably to do a dynamic oversampling so no movement gets larger then half of the smalles circle radius. That means when the user moved the mouse / touch very quickly the difference between the old position and the new position would be greater than the max allowed movement step. In this case you would run a while loop and interpolate between the old and the new position in smaller steps (our max allowed step size) until we reach the new postion.
There's still a problem when you need oversampling for both objects. In this case you have to interpolate both in the same loop or it's quite pointless.
edit
An example. If you have a movement code like this:
// C#
public float speed = 2000;
void Update()
{
transform.position += transform.forward * speed * Time.deltaTime;
CheckCollisions();
}
You would do something like this instead :
// C#
public float speed = 2000.0f;
public float maxMovementStep = 2.0f;
void Update()
{
float amount = speed * Time.deltaTime;
while (amount > 0)
{
float step = Mathf.Min(maxMovementStep, amount);
amount -= step;
transform.position += transform.forward * step;
CheckCollisions();
}
}
Thanks for the answer. What I wound up doing was, after the movements were applied, I checked to see if the disc overlapped with one of the children of the main object. If it did, I simply moved the disc away from the center of the object it overlapped with by the distance that they overlapped. It seems to work pretty well, and it looks natural enough. Your explanation was very helpful.
Thanks again!
Your answer
![](https://koobas.hobune.stream/wayback/20220613081556im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Game won't run on iPhone even with the device selected 0 Answers
IOS GUI slider 1 Answer
Getting a more accurate lat lng coordinate on mobile devices 0 Answers
GL ES1 vs ES2 (for iOS) 1 Answer