I'm making a platform game and I've looked at different ways to add collisions in a tile based game without rotation. But everything I look at assumes that in no case will one of the colliding objects be going fast enough to pass the other before collision is detected. I've tried using Box2D and Farseer but they were over complicated and ran quite slowly when making lots of tiles. I also tried my own method using 2D convex hulls but that ran too slowly as well. So is there a way to to detect collisions without a maximum speed or letting items pass each other that isn't over complicated and would work with lots of tiles? any help is much appreciated
Depend on objects and their movement and whole gameplay. if you are shooting bullet to some obstacle, you can calculate if bullet will intersect with obstacle before bullet hit it. you have positions, you can calculate distance between them. so you can check collision and distance.
other way, as #cwohlman suggested. you can have 2 collision boxes, one big "assumed" collision area and one excact that cover objects. so if object triggers assumed collision, you know that there i a chance that bullet will hit object and you do some detailed calculations if button will hit object or will pass above or under it. for determinating if object is in assumed collision area you can use circle collsion.
private bool DetectCircularCollision(Sprite a, Sprite b)
{
float radius = Math.Sqrt(a.Width / 2 * a.Height / 2 + b.Width / 2 * b.Height / 2);
float distance = Vector2.Distance(a.Position, b.Position);
if (distance < radius) return true;
return false;
}
so far i didn't encounter this problem, as all flying objects should be visible to players eye. if you move object 50px or 100px per frame player will not notice this or will be confused what is this.
You will probably need to combine few collision methods to achieve what you need. Advice, do not use pixel collsion as it's completly unnecessary and it's resuorce killer. Instead, cover objects with few bounding boxes or circles.
example where blue circle is assumed collision area, and red circles are exact collision area.
You might try a dual algorithm approach, using a simple algorithm first to deturmine if the objects 'might' have collided and if if so, use a complex algorithm to see if they did collide.
Related
i am creating a 3d top down shooter with unity and wanted to create an aim assist for it since hitting enemies is difficult. my idea was to create a trigger that slows down the rotation of the joystick on the weapon when the player aims at an enemy. i implement my rotation as follows:
float eulerY = (Mathf.Atan2(_JoystickShoot.Direction.x, _JoystickShoot.Direction.y) * 180 / Mathf.PI);
However, I don't know how to implement the slowdown now. The player should rotate slower than the actual rotation of the joystick.
My approaches have not really been successful so far.
does anyone have any idea?
thanks :)
You can add a variable that scales the rotation. Set it to 1, except when you're pointing at an enemy, where you set it to a value between 0 and 1 that feels good for you.
float eulerY = rotationScaling * (Mathf.Atan2(_JoystickShoot.Direction.x, _JoystickShoot.Direction.y) * 180 / Mathf.PI);
If you want to draw the crosshair towards an enemy, you can calculate the angle (or distance) to the closest enemy. If it is below a certain threshold you can adjust your rotation function to favor rotations towards the enemy over rotations away from it. You can use something like this:
float eulerY = (Mathf.Atan2(_JoystickShoot.Direction.x, _JoystickShoot.Direction.y) * 180 / Mathf.PI);
if (closest enemy is within threshold range)
if (eulerY * (difference in Y angle to closest enemy) < 0) // if we rotate away from the enemy we scale the rotation down
eulerY *= 0.5;
else // if we rotate towards the enemy we scale it up
eulerY *= 1.5;
You can adjust this for multiple angles as well, but just doing the same calculation for X and Y direction might feel a bit awkward. The reason is that in that case you have to compare it against the "true" angle/distance, not against the X and Y angles/distances individually.
I think it is more useful to talk about 'direction' rather than 'rotation'.
Presumably your ship travels and/or shoots in the same direction as the joystick is pointing in. This is a natural and intuitive relationship. "slowing down rotation" will most likely break this, making your interface less intuitive to use. There are also usually ways to go directly from a direction-vector to a rotation, for example Quaternion.LookRotation, avoiding the need to deal angles directly.
You could instead check if there is any enemy within a small arc, select the enemy closest to the center of the arc, and use the direction towards that enemy to fire in. Note that this can fail if enemies are moving and shots are slow, since it can prevent 'leading' your shots.
Other alternatives could be to simply make your enemies easier to hit. Make the enemies or shots larger, or possibly, just make the hitboxes larger. Or increase fire-rate and/or dispersion.
I know there's so many stuff on the internet about this, and I have looked at quite a lot of it, but I just can't get it to work with my code. I kinda know the maths behind it, but again struggling to get it into code.
I have 2 speed variables for the ball float xSpeed, ySpeed. Both are equal to 3 (or -3 depending on collision - I just have basic collision atm). I'm also using a rectangle for ball ballRect as well as the paddle paddleRect.
I'm updating the position as so:
ballRect.X += xSpeed;
ballRect.Y += ySpeed;
I've found bits of code, and tried doing it myself, but they just were really buggy. One would (I think) work on the first hit, but when it came to the next hit it would stick to the paddle.
double relativeBallPos = (paddleRect.X + ballRect.X);
double ballVelx = xSpeed;
double ballVely = ySpeed;
double angleRads = Math.Tan((ballVelx / relativeBallPos));
double angleInDeg = angleRads * (180 / Math.PI);
double angleOfReflection = (angleInDeg * 2);
ballVelx = ballVelx * angleOfReflection;
if (ballRect.X + (ballRect.Width / 2) < paddleRect.X + (paddleRect.Width / 2))
{
xSpeed = (float)-ballVelx;
}
else if (ballRect.X + (ballRect.Width / 2) > paddleRect.X + (paddleRect.Width / 2))
{
xSpeed = (float)ballVelx;
}
(This goes off at a (probably incorrect) angle and just goes straight up after the first hit)
Thanks for any help :)
If your ball intersects any horizontal threshold (the horizontal sides of the bricks, or of the paddle), negate ySpeed. If it intersects any vertical threshold, negate xSpeed. There, now you have a functional breakout game.
You can add a bit more polish by changing the angle of the ball when it hits the paddle based on the position of the collision along it, with center being a full reflect (ie negate ySpeed) and xSpeed getting a factor of the distance (positive or negative) of the distance from the center.
Yes, what you are seeing is completely normal, if your objects are moving very fast and game tick speed is slow, you may have glitches like sticking to the paddle or even missing the paddle completely, and just going straight through.
The solution to missing the paddle is increase game tick speed, i.e. process game moves more frequently.
Ball to paddle stickiness can be alleviated by doing a roll back of object movement in time. For example you have objects A and B, which are colliding at some point in time. If you simply reverse their X and Y speeds, you may end up with colliding again in the next point in time, so you would then reverse their speeds again, and so on, which appears as though it's stuck. It can sometimes get stuck on one only axis, so it will slide on the paddle, and then go straight down, which is just another side effect of the same issue.
How to do a roll back? You know where A is moving, and suppose B is a paddle, so it's static. You know that A is colliding with B at the moment. You can calculate a vector of A's movement and slide A back in time through that vector reversed. For example, if top left corner of the screen is (0,0), and A was moving at the speed of X=+10,Y=+10, you would move it back by whole or fraction of the step (depends on how complex you want to go with this), so by (-10,-10) or fraction thereof. You can use intersection rectangle to calculate precise values, and only move enough so the objects are barely touching.
Ideally, you would reflect the vector off the hit surface (use physics, i.e. hit angle = reflect angle) and before applying new speeds, move your ball in a way that it does not collide with paddle. To simplify, you can assume your hit surface is horizontal and is just a straight line, so your reflection formula is very simple.
This topic is well covered here (although using XNA, same principle applies):
Stuck in Wall after rectangle bounding box collision
For more than two days now I am struggling with this seemingly impossible problem: I have a composite GameObject (one parent, 10 children), each one hinged to at least another with angle limits and player-controlled motors. Moves perfectly as I wish.
Now I want to be able to flip it. After a while and many trials,rotation seems the best way in order to keep the angles (inverting localSpace does not respect them):
Vector3 rotPoint = new Vector3 (ParentGameObject.transform.position.x, myY, myZ);
ParentGameObject.transform.rotateAround (rotPoint, Vector3.up, 180.0f);
BUT, if the parent rotates as asked (180 degrees around its Y axis), every child flips but not around the same axis, rather around their own rotation center. This gives ridiculous results as hinges try to get back to the desired position. How could I fix this?
Many many thanks in advance...
In the end I figured out the problem. My problem had no valuable solution.
We can rotate the transform around the Y axis even in 2D, but NOT the rigidbody2D, which in the same object will invariably cause serious problems.
This is maybe one remaining inconsistency into Unity5's implementation of 2D.
I had to flip using localScale inversion and programmatically updated positions and rotations.
It sounds like the child GameObjects are rotating around their own pivots instead of the parents. I haven't got Unity installed at the moment to test this, but if you add an empty GameObject as a child of your parent (and with the same pivot point), then make all your other GameObjects a child of this, it should work.
You should not move or rotate a rigidbody if you don't have to. That will mess up the underlying physics calculations and physics engines won't be happy about it. Instead, you have other ways to interact with them
Apply force, torque
Apply acceleration, angular acceleration
Change speed, angular speed
If you have to move/rotate the object, you should also update positions, rotations, speeds, angular speeds of all of your hinged objects. That would not be easy. Give some more details if you unable to solve.
I am making a FPS game, I created a peaceful AI for the moment and when the character is died, I just want it to be oriented according to the normal below it. I show you the result for the moment :
as you can see, the character is flying, because the terrain is not straight.
I am trying (without success) to make something like that :
I have the (x,y,z) coordinates (character position) and the normal to the plane.
Yes the normal is always facing up, as you can see on my drawing, even if I drew it in the good pose. I dont understand when you are talking about the quaternion, which new normal are you talking about ?
I already have the normal of the plane under the character, so, part of the jobs is already done :)
Your character's death pose is always with the normal facing up, right?
And you want to rotate it to another normal.
You can find a Quaternion that represents the rotation between two vectors (up and the new normal) to rotate the mesh.
This question has the answer to that:
Quaternion from two vector pairs
To know the normal of your terrain, you can probably cast a ray down and get the normal from the collision information depending on the physics engine you are using.
Edit:
Some background info:
A quaternion represents a rotation. So what I'm suggesting is that you use the answer from the question I linked to calculate the rotation between the default orientation of the character's death pose (UP) to the new orientation (Terrain Normal)
Then you can just transform your dead character with the Quaternion and it'll follow the terrain's normal.
Here's a sketch: calculate Q from UP and N with the solution from the Link and rotate your character's model with Q:
I'm building a 3D game but i only plan on using a 2D perspective thus not taking the z axis into the equasion,
i want to be able to limit the movement of one of my models so it doesn't move out of the unmoving field of view,
when i was designing 2D it was simple just use clamp, but i cant seem to figurebout how to do this in 3d
any help would be much appreciated
Regards
Just use Vector3.Clamp(Vector3 value1, Vector3 min, Vector3 max) and use the constructor on Vector3 that takes a Vector2 and an int (for z value).
If you simply want to do the same thing as a 2D clamp would - Vector3.Clamp set the Y (usually 'UP') component of the two bounding vectors you pass to be 0.
I'm slightly confused on the question however, it seems that maybe what you are after is a form of collision detection with the view frustum This article may help with that if your model can fit into a bounding sphere relativity nicely.
You will need to for test collision vs all the planes which define the view space. If its a perspective camera your using, you'll need to get the Frustum Planes, otherwise if its an orthographic camera they are the planes that make the bounding box of the view space (a cuboid which is orientated the same way as the camera).
So you want in pseudocode:
if (object.position+movementVec is in view of camera)
object.position+=movementVec;