I am creating a 3D gravity simulation in Unity. I have everything working correctly except the collision response. I want to make collision resolve calculations from the exact point of impact rather than the time of the current timestep. I have looked around, and I think I have found the correct equation to determine the exact time of collision. However, whenever I try to execute the code, I am getting a NaN error as a result. I have tried everything I can think of to fix the issue, but nothing seems to remedy the error. Can someone take a look at my code and see if you can identify any obvious errors I may have missed?
The method I am having trouble with was designed to determine the exact time of impact between two spheres which I know have collide within the last timestep. If each timestep is 1, the method is meant to return a number between 0(the current timestep) and 1(the previous timestep) that the collision occurred.
This is the formula I am using
Vector3 velocity2MinusVelocity1 = particle2.GetComponent<Particle>().Velocity - particle1.GetComponent<Particle>().Velocity;
Vector3 separationVector = particle1.transform.position - particle2.transform.position;
return ((-(Vector3.Dot(separationVector, velocity2MinusVelocity1)
/ (Mathf.Pow(Vector3.Magnitude(velocity2MinusVelocity1), 2))))
-
(Mathf.Sqrt(
Mathf.Pow(
Vector3.Dot(separationVector, velocity2MinusVelocity1)
/ Mathf.Pow(Vector3.Magnitude(velocity2MinusVelocity1), 2)
, 2)
-
Mathf.Pow(Vector3.Magnitude(separationVector), 2)
- Mathf.Pow(particle1.GetComponent<Particle>().Radius
+ particle2.GetComponent<Particle>().Radius
,2)
/ Mathf.Pow(Vector3.Magnitude(velocity2MinusVelocity1), 2)
)));
I apologize if the structure is a little hard to follow. I tried to make it as easily readable as possible
Related
I'm using Physics2D.BoxCast in Unity(2019.4.19f1).
I have a collider2D at position==(0,0) with scale==(1,1)
Then I call a Physics2D.BoxCast:
var hit = Physics2D.BoxCast(new Vector2(0, 2), new Vector2(1, 1), 0, new Vector2(0, -1));
It is a Box Ray Cast like the following pic:
I have a hit returned.
But hit.distance == 0.9950001, which is supposed to be 1.
I guess there may be some inaccuracy in Physics2D.BoxCast. But I have no idea how much the inaccuracy can be.
Then I do some searching and find "Default Contact Offset" may be related to my problem.
I change "Project Setting → Physics2D → Default Contact Offset" to 0.001(default is 0.01).
Run the code again. But now I get hit.collider == null.
Now I'm more confused about Physics2D.BoxCast.
It may be helpful to learn something about how Physics2D.BoxCast work. But I do not know where to find them.
Added 2021.3.1
I did several experiments about "DefaultContactOffset".(link)
The experiment results show that:
If the DefaultContactOffset is about 0.002~0.01. Most of the time, the error in hit.distance is about 0.005.
If the DefaultContactOffset is about 0.02~0.1. The error in hit.distance is larger.
I actually don't know Physics2D.BoxCast but from what i understand it just moves a box to your target at a "speed". Now I done similar calculations in opengl and any collision like this using a speed over time will result this behavior. You can't expect to get a result %100 accurate. imagine every frame you move the red box 5 points instead of a small scale. You red box would just jump over the white box and you would not get a hit result..
Now internet says " Reducing Default Contact Offset can mean that collisions don't have enough of a buffer to work correctly. " so i guess Physics2D.BoxCast just check if 2 objects is going to collide and not if they are colliding which would explain why you get a null hit when you make the ofset so small.
Edit:This was a comment but was too long.
I have started to make Pacman and would like to know how can i write in my code the direction where the Ghost is going ? So if the transform.position.y is growing, its obvious Up Direction and so on....
This is for the Direction Change if they're hit the Wall.
Any suggestions?
It depends on how you've got your game set-up. One manual way you could go about it is by saving the position in a frame, and in the next frame you calculate the difference between the two positions (the previous frame and the actual frame), and divide that by the time that has passed (Time.deltaTime).
Another way you could go about it (and I would recommend if possible) is simply getting the Rigidbody component and checking the velocity attribute: https://docs.unity3d.com/ScriptReference/Rigidbody-velocity.html
Keep in mind, since this is a beginner's question, that the fact that an object is moving in a certain direction may not come from a ribidbody. As I said, this depends on your exact set-up.
Okay so, i have a tiled map (obviously) and implemented a collision detection system which is working really well for me. It has trouble with those pesky corners though. I do know why that is, since i don't even check the corners. And that's the point, i don't know how to do that. So, first of all here is my current code:
Body body = currentObject.Body; // Body is a class storing position, velocity, bounds and so on.
int tileDimensions = level.TileWidth; // Since the tiles are squares...
int leftTile = body.Bounds.Left / tileDimensions;
int topTile = body.Bounds.Top / tileDimensions;
int rightTile = (int)Math.Ceiling((float)body.Bounds.Right / tileDimensions - 1);
int bottomTile = (int)Math.Ceiling(((float)body.Bounds.Bottom / tileDimensions) - 1);
if (body.Velocity.Y > 0) // Moving down.
{
for (int x = leftTile; x <= rightTile; x++)
{
for (int y = bottomTile + 1; y <= (bottomTile + 1) + (body.Velocity.Y / tileDimensions); y++)
{
if (tiles[x, y] != null && !tiles[x, y].IsPassable)
{
newVelocity = new Vector2(body.Velocity.X, MathHelper.Clamp(body.Velocity.Y, 0, tiles[x, y].Body.Bounds.Top - body.Bounds.Bottom));
body.Velocity = newVelocity;
break;
}
}
}
}
So thats just for moving down. There are 3 other constructs like that for up, left and right. The only real difference is the loop and the way i clamp the velocity.
As you can see i just loop through all tiles i could potentially collide with. Then i clamp the velocity, which will slow it down in case there is indeed a tile in it's way.
Now, i'm afraid it's hard to explain my problem with just words, so i'll have to post a picture too.
In this screenshot yellow means unpassable tile, black are the tiles the above code is currently checking for collision and red is the player.
To show you what the problem is, imagine i were to accelerate up and right in this frame. As you can see, there would be a collision with the tile on the upper right of my player but the player will just move into the tile since i don't check it for collision. And i will not check it in the next frame either, since i don't check for blocks i'm in because ... i don't even know, that would betray the whole idea behind my code, wouldn't it ? :P
Of course, i could just extend my "searching" range, but then i would collide with tiles, i shouldn't collide with.
Currently, i'm fixing this with an extra check for all the tiles my bounds are overlapping with and... you know, just moving the player back if i find any. But this is really messy and it doesn't preserve the initial velocity. If the player hits a corner he will move into it, i will detect that, move him back and null his velocity. That just doesn't feel right, it's clunky.
I just can't seem to figure out a good way of dealing with such cases. I doesn't happen too often (since it's really hard to reproduce) but once in a while it happens and that is of course unacceptable.
I'd really like to not even have a bugfix-type thing for it but to integrate it in my other code as nicely as possible. This is not mandatory, but it would be cool to be able to do that.
So i'd really appreciate if anyone of you guys could throw something at me.
Anyway, i hope you were able to follow what i was trying to say. Since english isn't my native language it's a little hard to explain such things at times. Also i'm just really bad at explaining things :/
I suppose you could just add 4 more cases, handing when the currentObject is moving in a diagonal, no?
However, you might want to investigate collision based on bounding volumes.
I've got two polygons defined as a list of Vectors, I've managed to write routines to transform and intersect these two polygons (seen below Frame 1). Using line-intersection I can figure out whether these collide, and have written a working Collide() function.
This is to be used in a variable step timed game, and therefore (as shown below) in Frame 1 the right polygon is not colliding, it's perfectly normal for on Frame 2 for the polygons to be right inside each other, with the right polygon having moved to the left.
My question is, what is the best way to figure out the moment of intersection? In the example, let's assume in Frame 1 the right polygon is at X = 300, Frame 2 it moved -100 and is now at 200, and that's all I know by the time Frame 2 comes about, it was at 300, now it's at 200. What I want to know is when did it actually collide, at what X value, here it was probably about 250.
I'm preferably looking for a C# source code solution to this problem.
Maybe there's a better way of approaching this for games?
I would use the separating axis theorem, as outlined here:
Metanet tutorial
Wikipedia
Then I would sweep test or use multisampling if needed.
GMan here on StackOverflow wrote a sample implementation over at gpwiki.org.
This may all be overkill for your use-case, but it handles polygons of any order. Of course, for simple bounding boxes it can be done much more efficiently through other means.
I'm no mathematician either, but one possible though crude solution would be to run a mini simulation.
Let us call the moving polygon M and the stationary polygon S (though there is no requirement for S to actually be stationary, the approach should work just the same regardless). Let us also call the two frames you have F1 for the earlier and F2 for the later, as per your diagram.
If you were to translate polygon M back towards its position in F1 in very small increments until such time that they are no longer intersecting, then you would have a location for M at which it 'just' intersects, i.e. the previous location before they stop intersecting in this simulation. The intersection in this 'just' intersecting location should be very small — small enough that you could treat it as a point. Let us call this polygon of intersection I.
To treat I as a point you could choose the vertex of it that is nearest the centre point of M in F1: that vertex has the best chance of being outside of S at time of collision. (There are lots of other possibilities for interpreting I as a point that you could experiment with too that may have better results.)
Obviously this approach has some drawbacks:
The simulation will be slower for greater speeds of M as the distance between its locations in F1 and F2 will be greater, more simulation steps will need to be run. (You could address this by having a fixed number of simulation cycles irrespective of speed of M but that would mean the accuracy of the result would be different for faster and slower moving bodies.)
The 'step' size in the simulation will have to be sufficiently small to get the accuracy you require but smaller step sizes will obviously have a larger calculation cost.
Personally, without the necessary mathematical intuition, I would go with this simple approach first and try to find a mathematical solution as an optimization later.
If you have the ability to determine whether the two polygons overlap, one idea might be to use a modified binary search to detect where the two hit. Start by subdividing the time interval in half and seeing if the two polygons intersected at the midpoint. If so, recursively search the first half of the range; if not, search the second half. If you specify some tolerance level at which you no longer care about small distances (for example, at the level of a pixel), then the runtime of this approach is O(log D / K), where D is the distance between the polygons and K is the cutoff threshold. If you know what point is going to ultimately enter the second polygon, you should be able to detect the collision very quickly this way.
Hope this helps!
For a rather generic solution, and assuming ...
no polygons are intersecting at time = 0
at least one polygon is intersecting another polygon at time = t
and you're happy to use a C# clipping library (eg Clipper)
then use a binary approach to deriving the time of intersection by...
double tInterval = t;
double tCurrent = 0;
int direction = +1;
while (tInterval > MinInterval)
{
tInterval = tInterval/2;
tCurrent += (tInterval * direction);
MovePolygons(tCurrent);
if (PolygonsIntersect)
direction = +1;
else
direction = -1;
}
Well - you may see that it's allways a point of one of the polygons that hits the side of the other first (or another point - but thats after all almost the same) - a possible solution would be to calculate the distance of the points from the other lines in the move-direction. But I think this would end beeing rather slow.
I guess normaly the distances between frames are so small that it's not importand to really know excactly where it hit first - some small intersections will not be visible and after all the things will rebound or explode anyway - don't they? :)
Was wondering if anyone has knowledge on implementing pathfinding, but using scent. The stronger the scent in the nodes surrounding, is the way the 'enemy' moves towards.
Thanks
Yes, I did my university final project on the subject.
One of the applications of this idea is for finding the shortest path.
The idea is that the 'scent', as you put it, will decay over time. But the shortest path between two points will have the strongest scent.
Have a look at this paper.
What did you want to know exactly??
Not quite clear what the question is in particular - but this just seems like another way of describing the Ant colony optimization problem:
In computer science and operations
research, the ant colony optimization
algorithm (ACO) is a probabilistic
technique for solving computational
problems which can be reduced to
finding good paths through graphs.
Well, think about it for a minute.
My idea would to divide the game field into sections of 32x32 (or whatever size your character is). Then run some checks every x seconds (so if they stay still the tiles around them will have more 'scent') to figure out how strong a scent is on any given tile. Some examples might be: 1) If you cross over the tile, add 3; 2) if you crossed over an adjacent tile, add 1.
Then add things like degradation over time, reduce every tile by 1 every x seconds until it hits zero.
The last thing you will need to worry about is using AI to track this path. I would recommend just putting the AI somewhere, and telling it to find a node with a scent, then goto an adjacent node with a higher/equal value scent. Also worry about crossing off paths taken. If the player goes up a path, then back down it another direction, make sure the AI does always just take the looped back path.
The last thing to look at with the AI would be to add a bit of error. Make the AI take the wrong path every once in a while. Or lose the trail a little more easily.
Those are the key points, I'm sure you can come up with some more, with some more brainstorming.
Every game update (or some other, less frequent time frame), increase the scent value of nodes near to where the target objects (red blobs) are.
Decrease all node scent values by some fall-off amount to zero.
In the yellow blob's think/move function get available nodes to move to. Move towards the node with the highest scent value.
Depending on the number of nodes the 'decrease all node scent values' could do with optomisation, e.g. maybe maintaining a a list of non-zero nodes to be decreased.
I see a big contradiction between scent model and pathfinding. For a hunter in the nature finding the path by scent means finding exactly the path used by the followed subject. And in games pathfinding means finding the fastest path between two points. It is not the same.
1. While modelling the scent you will count the scent concentration in the point as the SUM of the surrounding concentrations multiplied by different factors. And searching for the fastest path from the point means taking the MINIMUM of the times counted for surrounding points, multiplied by the different parametres.
2. Counting the scent you should use recursive model - scent goes in all directions, including backward. In the case of the pathfinding, if you have found the shortest paths for points surrounding the target, they won't change.
3 Level of scent can rise and fall. In pathfinding, while searching for minimum, the result can never rise.
So, the scent model is really much more complicated than your target. Of course, what I have said, is true only for the standard situation and you can have something very special...