moving on terrain - preventing move to high places xna - c#

I have a fps camera and a model of a gun that follows her, and I have a terrain, the camera is moving on the terrain just fine, but I have a problem, I want to stop the movement if the camera is moving to high place (if it tries to move to a cliff or another high place I want to stop this option of moving to very high places) I dont mean preventing to move on high places I mean only when there is very high slope, hope you will understand and will be able to help!

If you are able to get information from the terrain where you are walking on, it is also possible to get information on the angle of the terrain.
The terrain exists out of different triangles, since it is a mesh. Every triangle has 3 vertices, but also has a so called: normal.
The normal of the face, is the direction that is pointing upwards. With simple angle calculations, you can check if the angle is too steep or not.
// in pseudo code:
public bool TooSteep(Vector3 position, float maxAngle)
{
// get your information from the terrain
// there is probably some function, or you have to write it,
// that returns the normal from the terrain
Vector3 normal = myTerrain.GetNormal(position);
// then we calculate the angle between the 'up'-vector and our normal vector
if (Vector3.Angle(normal, Vector3.up) > maxAngle)
return true;
else return false;
}
So suppose that our max angle is 45 degrees and we have a very steep normal. The angle between the up-vector and the normal will be large. Larger than our maxAngle and will therefore return: yes, it's too steep.

Related

How to calculate the 3D vector perpendicular to a polygon surface in a specific direction

I'm creating an asteroid mining game in Unity 3D, where "down" is the center of the planet you are on (So I am mostly using local rotations when dealing with vectors). I have a working physics-based character controller, but it has problems dealing with slopes. This is because when I add a force to the character, currently it pushes along the player's forward vector (see picture). What I want to do is calculate the vector that is parallel to this terrain surface, but in the direction that the player is facing (so that the player can move up the slope).
I originally thought that i could just find the vector perpendicular to the normal, but then how do I know which direction it will be in. Also complicating matters is the fact that the player could be oriented in any way in relation to the global x, y, and z.
Either way, I have the surface normals of the terrain, I have all of the player's directional vectors, but I just can't figure out how to put them all together. I can upload code or screenshots of the editor if necessary. Thanks.
The usual way is to factor out the component of the forward vector that is parallel to the surface normal:
fp = f - dot(f, n) * n
See vector rejection.
This formulation will also make fp shorter the steeper the slope is. If you don't want that, you can re-scale fp afterwards to have the same length as f.

Projectile Not Correctly Inheriting Parent Velocity (Unity3D)

I am trying to fire projectiles from a player who is moving at very high speeds. The issue is that the bullets do not seem to inherit the angular velocity. If the player is moving in a straight line at 500 U/s, then the bullet correctly inherits that velocity and adds its own speed onto that:
GameObject bullet = Instantiate(projectile, gun.transform.position, gun.transform.rotation);
bullet.GetComponent<Rigidbody>().velocity = r.velocity + bullet.transform.forward *bulletSpeed;
However, if the player is turning really quickly, it does not inherit the rotational velocity, and the bullet looks like it veers off to the side.
How can I implement this? I tried assigning the angular velocity of the player to the bullet, but this just caused the bullet to spin while moving in the same direction.
Some extra details:
I am using rigidbody.MoveRotation() to rotate my player, but I manually calculated angularVelocity to assign it to the bullet
I tried moving the player with AddTorque(), but could not produce any results with the bullets
The immediate problem is that the projectile isn't part of the physics simulation until the moment you create and launch it, meaning the rotation of the player up to that point will not be able to influence its movement. I suppose this could work if you created the projectile at the start, attached it to the gun with a weak joint, then broke the joint and added to its velocity when it was fired - but it really would be simpler if you just "faked" it.
Applying Circular Motion
This is similar to a classic circular motion example you'd find in a physics textbook. When your bullet travels in a circle around the player (inside the gun), its normal path (if released) would be tangent to the circular path around the player. So when the bullet is fired (and hence released from the circular path), that angular velocity of the player would translate into a linear velocity of the bullet. Here's a simple diagram I put together that represents the situation with a ball on a string, being spun in a circle:
Getting the Tangential Velocity of the Bullet
You don't want to be applying any kind of angular velocity to the projectile after it has been launched - as you saw, this will only spin the projectile on its own axis. Rather, you want to apply an additional velocity vector to the projectile, which is tangent to the rotation of the player (and perpendicular to the facing of the bullet). So how do we do this?
Well, as per this website, the formula for tangential velocity at any point on something spinning in a circle is:
velocity = angularVelocity x radius
A key point to remember is that the angularVelocity is in radians, not degrees.
So, let's put this all together. Here's a general idea of how you might code this:
FireGun() {
// Assumes the current class has access to the rotation rate of the player
float bulletAngularVelocityRad = Mathf.Deg2Rad(rotationRateDegrees)
// The radius of the circular motion is the distance between the bullet
// spawn point and the player's axis of rotation
float bulletRotationRadius =
(r.transform.position - gun.transform.position).magnitude;
GameObject bullet =
Instantiate(projectile, gun.transform.position, gun.transform.rotation);
// You may need to reverse the sign here, since bullet.transform.right
// may be opposite of the rotation
Vector3 bulletTangentialVelocity =
bulletAngularVelocityRad * bulletRotationRadius * bullet.transform.right;
// Now we can just add on bulletTangentialVelocity as a component
// vector to the velocity
bullet.GetComponent<Rigidbody>().velocity =
r.velocity + bullet.transform.forward * bulletSpeed + bulletTangentialVelocity;
}
Hope this helps! It's never a bad idea to read up on some basic kinematics/mechanics when you're working with game physics, since sometimes relying on the game physics is actually more complicated than just devising your own solution.

XNA Monogame Mouse Projectile Click

I am coding for a game and I have it running fine and all, but I ran into the issue of projectiles. I have no idea of how to calculate the mouse position and send a projectile over. I've looked though many stackoverflow tutorials and many youtube videos, but they are either too vague or very very complex. Could someone please explain the process? I have been coding in C# for 2 years now, so I do have background knowledge. Please Help!
Well, you don't tell what kind of game you are working on and what the projectile you want to "send over", whatever that means but here are a few pointers, maybe one will help:
#1: If you are doing a 2D game, and you want to send a projectile from some point toward the mouse cursor, then you simply get the position of the mouse by calling GetState() on your MouseState instance, and reading it's X and Y properties, then get the direction of the projectile by subtracting the location of the origin of the projectile from the mouse position. Then you can move the projectile along that line by storing the time you launched it, subtracting that every frame from the actual time to get how long it has been on its way and then adding that many times it's speed times the normalized direction to its origin coordinates.
Example:
For this I assume you have a Projectile class that has Vector2 field called origin, one called direction, one called position, a float called speed and an int called startTime and you have an instance of it with origin and speed already set. Modify as necessary for your actual code.
MouseState ms = new MouseState();
in your Update method:
ms.GetState();
projectile.direction = new Vector2(ms.X, ms.Y) - projectile.origin;
projectile.direction.Normalize();
projectile.position = projectile.origin + projectile.speed * (gameTime.TotalGameTime.TotalMilliseconds - projectile.stratTime) * projectile.direction;
And then in the Draw method you just draw the projectile to the coordinates in projectile.position.
#2: You are doing a 3D game and want to shoot a projectile originating from your camera and directed toward whatever your mouse is pointing at. You will need to generate a Ray with something like this:
private Ray getClickRay(Vector2 clickLocation, Viewport viewport, Matrix view, Matrix projection)
{
Vector3 nearPoint = viewport.Unproject(new Vector3(clickLocation.X, clickLocation.Y, 0.0f), projection, view, Matrix.Identity);
Vector3 farPoint = viewport.Unproject(new Vector3(clickLocation.X, clickLocation.Y, 1.0f), projection, view, Matrix.Identity);
Vector3 direction = farPoint - nearPoint;
direction.Normalize();
return new Ray(nearPoint, direction);
}
From there you can get the position of your projectile the same way as above, only using Vector3-s instead of Vector2-s.
#3: You want to simulate some sort of launcher and do a physical simulation on the trajectory of the projectile. Since I find this less likely than the first two I'll just describe the idea: you set a minimum and maximum rotation for your launcher along 2 axes, link each rotation to the ratio of the full width and length of your screen to the mouse position, and then use the angles and whatever other variables you have to calculate the direction and speed of the projectile at launch, then simulate physics each frame.
I hope one of these will help.

Unity 3D rotating a game object with the left stick causes object to Jitter back and forth

So I'm trying to make a third person controller that uses the PS4 controller with the left stick controlling the rotation and movement and the right stick controlling the camera separately. my problem right now is that when I apply this script to my game object it causes the player to Jitter back and forth. Any thoughts as to why or how I can fix it thanks.
void Update ()
{
//Defaults to the left Stick
float hAxis = Input.GetAxis("Horizontal");
float vAxis = Input.GetAxis("Vertical");
Vector3 NextDir = new Vector3(hAxis, 0, vAxis);
if (NextDir != Vector3.zero)
{
transform.rotation = Quaternion.LookRotation(NextDir); //this rotates the character correclty but causes jitter
transform.Translate(NextDir.x * Time.deltaTime * 5, NextDir.y * Time.deltaTime * 5, NextDir.z * Time.deltaTime * 5, Space.Self);
}
}
}
Perhaps the "jitter" you see is the game code accurately rotating the object according to the data it is getting from the joystick. I am guessing that by "jitter" you mean the rotation is bouncing back and forth between clockwise and counter-clockwise sporadically, when you think that you are smoothly rotating the joystick in one direction (clockwise or counter-clockwise). (If not, please describe the jitter.)
If this is the case, since you are reading the joystick at every frame, the joystick is probably picking up values that cause the vector to bounce back and forth. So, try adding a tolerance and only taking action if the vector changes by a certain amount. Or, only accept vectors that cause the rotation to continue in the same direction (CW or CCW) as the previous frame, unless the change is more than some certain amount, which would indicate that the player really does want to start turning back in the other direction.
Try increasing the value of the dead property in the horizontal and vertical axis. This should mean the joystick has to be moved further out of it's resting position before reporting a value.
It's located in Edit->Project Settings->Input modify the value for the second occurrences of those two properties ( the first two are for the keyboard )

Different method for collision detection using faces of a rectangle

I have been working on and off of a certain game I'm making (trying to get it finished!) and a problem that has been unsolved for a while in it is the collision detection between a ball and a square.
Basically what I want to happen eventually is depending on the angle/way the rectangle is facing, I want the ball to bounce of it accordingly (I know I could just inverse the ball direction before/as it hit the square).
At the moment though, my current problem is trying to inverse the correct X and Y components depending on the side/face that the ball collides with the square, e.g. if the ball hits the right side of the square, then I need to inverse the ball's X component.
This doesn't seem to work and I was wondering if I could somehow label each side of the rectangle, in terms of for the top of it label that 'face 1' or something, then for the right side of it 'face 2' or 'side 2', etc...
I have provided some code below (this is the code I'm using now):
//(collision with right side of square)
if (theBall.GetRectangle.Left <= thePaddle.GetRectangle.Right)
{
theBall.pVelocity.X = -theBall.pVelocity.X;
}
//(collision with bottom of square)
if (theBall.GetRectangle.Top <= thePaddle.GetRectangle.Bottom)
{
theBall.pVelocity.Y = -theBall.pVelocity.Y;
}
I have written the code for the other 2 sides of the rectangle but they are just the opposite of the two above, i.e. for collision with top of rectangle = opposite of bottom, etc.
EDIT: the object I am checking against if the ball has collided with DOES NOT move, I mean it only rotates... so I don't know if this is important (it probably is, therefore I apologise for missing this info out at the start).
EDIT # 23:36: ok, I have tried something.... and it hasn't worked... :(
public Vector2 DistBetweenBallAndBlock(Paddle thePaddle, Ball theBall)
{
Vector2 centreOfBall = new Vector2(theBall.Texture.Width / 2, theBall.Texture.Height / 2);
float distX = thePaddle.Position.X - centreOfBall.X;
float distY = thePaddle.Position.Y - centreOfBall.Y;
if (distX < 0)
{
distX = -distX;
}
if (distY < 0)
{
distY = -distY;
}
return new Vector2(distX, distY);
}
I have then tried to just print the result just to get an idea of what's going on and what sort of values are being output:
Vector2 a = ball.DistBetweenBallAndBlock(paddle1, ball);
angleOfPaddle = Math.Atan2(a.Y, a.X);
I then just print this value to screen, however I am getting the same result of 0.63...
To detect a collision between Rectangles you could use Rectangle.Intersect method, instead of checking the objects' sides.
And to detect which side of the rectangle is hit, you can compute the Vector2 between the ball center and the rectangle center. Getting its angle with Math.Atan2 you can easily know which face of the rectangle has been hit.
Looked up some Vector stuff, based on my comment.
Collision Style
The optimal way of colliding with a circular object is to collide using a vector between it and the nearest point of the object you're checking against. If the distance is less than or equal to the radius of the circle, there is a collision. The advantages of this method are that you don't have to keep track of a rectangle, you get circular collision, and you get the angle of the collision from the vector.
How You Do It
I'll assume you have some strategy to keep from considering every object every frame, and keep to the basic problem. Your paddle has 4 vertices, one for each corner. Because your ball is essentially a vertex with a picture drawn over it, you can easily check the distance between the ball and each corner of your paddle. Two will be nearest. From there, it's just a matter of finding out if that edge collides. I found a solution to that here, which includes a nice formula.
Does that help?

Categories