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.
Related
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.
I am a begginer. I am using Monogame and Farseer Physics Library in C#. (latest versions)
In my game, whenever my ball (circle) hits the corner of a rectangle, (or even another circle), it is supposed to only change direction on the Y-Axis.
However, it does not only change direction on the Y-Axis, (as intended), but it also moves a small amount to the right as well (or the left accordingly), depending on how you hit the corner (or another circle). It is as if some force is being put on the ball, making it move on X-Axis as well.
This movement is cool and all, and it makes a lot of sense, but in my game, it does not, therefore i want to get rid of it.
How is this possible ? I am guessing i have to change some default values.
This what my coding looks like:
BallBody.BodyType = BodyType.Dynamic;
BlockBody.BodyType = BodyType.Static;
Ball.LinearVelocity = new Vector(0,-1); // ball going up
BallBody.OnCollision += Ball_OnCollision;
public bool Ball_OnCollision(Fixture f1, Fixture f2, Contact contact)
{
// if the Ball (f1), collides with the Block (f2)
if (f2.Body == BlockBody)
// change the direction of the Ball on Y-Axis
Ball.LinearVelocity = new Vector(0,-1);
return true;
}
Also with high speeds, this occurs:
Even though the ball is never able to pass through the Block (tunneling), I want to know how could i possible fix that so that the ball never enters the Block area ?
Unfortunately, this is surprisingly difficult to do with Box2D. The best I could manage when I tried, was to record the velocity of the ball when the contact started, and then when the contact ends, manually set the velocity to what I wanted. That works fine when the ball only begins and end contact with one block at a time, but in some cases the ball can begin touching two blocks in the same time step. You would have to look at the arrangement of the blocks it touched, and calculate for yourself what angle you would expect it to bounce away at. Eventually I just gave up and did not bother to cover that case.
I've already asked this question on the OpenTK forums but there doesn't seem to be anyone able to respond. (http://www.opentk.com/node/3638)
In OpenTK, I'm trying to get a balance value of -1 to 1 converted to the left/right audio channels. When 0 (default value) both sides should be at 100% gain. When 1 100% for right and 0% for left and the opposite for -1. I'm having a hard time trying to get this to work in OAL seeing as this is actually my first time working with it.
So far I've tried:
After OAL initialization:
AL.DistanceModel(ALDistanceModel.LinearDistanceClamped);
For each new source:
AL.Source(SourceId, ALSourcef.MaxDistance, 1f);
AL.Source(SourceId, ALSourceb.SourceRelative, false);
For setting the balance:
float balance = 0f; //(-1f to 1f)
OpenTK.Vector3 position = new OpenTK.Vector3(balance, 0f, 0f);
AL.Source(SourceId, ALSource3f.Position, ref position);
This will make the audio go just above 100% on the left channel and 0% on the right for all negative values of balance and just above 100% right 0% left for all positive values, so I'm kinda stuck.
How should I go about doing this? Any help is appreciated!
Gr.Viller
BTW: This looks like a near-duplicate of the unanswered OpenAL 2d panning C++.
Using the OpenAL Soft mailing list I've got the answer I needed:
In FNA we do something like this, but it's probably not ideal (if not just incorrect):
https://github.com/flibitijibibo/MonoGame/blob/monogame-sdl2/MonoGame.Framework/Audio/SoundEffectInstance.cs#L58
I know for sure that this doesn't provide hard panning, but you probably didn't really want to do hard pans anyway. We do that work to keep things at the 1.0f distance, but if attenuation isn't required for your project, you can turn that off and possibly save some time/effort:
https://github.com/flibitijibibo/MonoGame/blob/monogame-sdl2/MonoGame.Framework/Audio/OpenALDevice.cs#L102
-Ethan
TL;DR:
Disable the distance system with:
AL.DistanceModel(ALDistanceModel.None);
Then set the balance like this:
AL.Source(SourceId, ALSource3f.Position, balance, 0f, (float)Math.Sqrt(1 - Math.Pow(balance, 2)));
Basically creating a half-circle on the Z-axis to always keep the same distance from the listener while shifting the direction to the audio.
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
I'm trying to move a body:
if (ks.IsKeyDown(Keys.Up)) {
rocket.ApplyImpulse(new Box2DX.Common.Vec2(0, 30f), rocket.GetPosition());
}
Oddly, the body only moves when the key is released. Why is this? I've been looking at the manual but can't figure it out.
When I remove the conditional, and just have the applyImpulse() call in Step(), the rocket continually has the animation of thrusters but never actually moves. (As if I had been holding down the Up key the entire time.)
Looks like what I really need to get this working is a better understanding of what the first argument to applyImpulse() does:
new Box2DX.Common.Vec2(0, 30f)
What is the significance of the two values in the vector?
UPDATE This works much better:
rocket.ApplyImpulse(new Box2DX.Common.Vec2(0, -1), rocket.GetPosition());
It looks like if the second value in the force vector is negative, the object rises on the screen. Before, the impulse applied was just slamming it into the floor. When I released the key, it would sometimes bounce back, if the impulse had been strong enough.
Regarding your update: In XNA, depending on how you've situated your camera, negative Y is up. If you want the rocket to go up, you have to apply a force in that direction.
That makes no sense as to why it only moves when it's released, is there nothing else interfering with it elsewhere such as another keyboard input hidden somewhere? I only ask as it could be that another keyboard input statement in conflicting with another and causing the problem.