Finding the last Vector of a right angled triangle - Unity - c#

For Context: I'm 90% of the way through making a wall running system in Unity, and I need help finding 2 Vector3's that I can use for a check and for adding velocity to the player to get them to move in the correct direction.
More specifically, I'm getting two Vector3's to the right and left of a contact point with a wall, then getting the distance between the right point and the players previous position, and the distance between the left point and the players previous position. Whichever point is further away from the player, is the direction we are travelling, and if you take that point and - the contact point from it and normalize that, the function returns the Vector3 to use to add velocity to the player.
Currently I'm using this function to do this for me (where hit is the contact point between the player and the wall):
Vector3 CalculateWallRunDirection(Vector3 hit, Transform wall)
{
Vector3 rightPos = hit + wall.forward;
Vector3 leftPos = hit + (wall.forward * -1);
float rightDis = Vector3.Distance(rightPos, prevPlayerPos);
float leftDis = Vector3.Distance(leftPos, prevPlayerPos);
if (rightDis < leftDis)
{
return Vector3.Normalize(leftPos - hit);
}
else
{
return Vector3.Normalize(rightPos - hit);
}
}
This works well when it works... but the problem is, because I'm using the Transform.forward of the wall to determine where these points are, if you try to wall run on the front or back face of an object, it will throw to into the wall instead of along it and the player will become stuck.
TL;DR: I need another way to determine two Vector3's instead of using transform.forward + original Vector3. From a top-down view, the problem could be displayed as this. A is the player, B is the contact point with the wall. Find C and D:
Please explain your answer, I'm not too great at math.

You were essentially trying to recreate Vector3.ProjectOnPlane(). You probably want to use that instead.
eg
Vector3 A = Vector3.ProjectOnPlane(B, C);
// A is the new velocity vector parallel to the wall
// B is the old velocity of the player at the point of impact
// C is the normal of the plane of impact
You can easily find C in the OnCollisionEnter event, simply get the contact point's normal.
Note B doesn't need to be normalized, but if it is, A will be a normalized Vector3 as well.

Related

#Unity Cube Movement (Jumping +1 Forward/Right/Backward/Left)

Hey stackoverflow Community,
First of all:
I'm still very new about programming with C# and Unity.
My question:
I'm working on an idea for a Movement of a Cube.
It is planned that the cube will move forward by pressing a key (W-Key). But it shouldn't just move forward. It should jump forward to the next point. So always plus 1 of its axis into which it should go. Accordingly, it is only intended to go forward, right, down, left. He won't be able to jump over behind. You should also see that the cube jumps in the respective direction, so it should not teleport itself. :D
Does anyone have an idea how I can realize this movement?
I am very much looking forward to your ideas.
(Sorry if my English is not so good, my English not the best. ^^)
best regards
xKarToSx
So, in order to understand movement, it's best to first understand Vectors in Unity. Since you want to be moving the cube in the forward direction, I'm going to assume this is a 3D game, in which case you want to use a Vector3.
A Vector3 has three components: X, Y, and Z. Each component is tied to an axis. In simple terms, X is tied to left and right, Y is tied to up and down, and Z is tied to forward and back. So, Vector3 position = new Vector3(0, 1, 2); will be a vector that is 1 unit above and 2 units in front of the starting position.
Assuming you've attached this script to the cube you want to move, you can track its position with transform.position. So, if you want to move the cube one unit forward, your code would look something like this:
if(Input.GetKeyDown(KeyCode.W)) // This code will activate once the user presses W.
{
transform.position += new Vector3(0, 0, 1);
}
That will move the cube one unit forward in the Z direction. However, you don't want it to teleport, you want to see it move, correct? In that case, you want to check out Unity's Vector3.Lerp function. Basically, you would use it to smoothly transition an object between two defined positions. You'll need to implement a timer and a for loop in order to make this work correctly.
So, to summarize, for moving one unit forward in the Z direction, your code would look something like this:
if(Input.GetKeyDown(KeyCode.Z))
{
float startTime = Time.time; //Time.time is the current in-game time when this line is called. You'll want to save this to a variable
float speed = 1.0f; //The speed if something you'll want to define. The higher the speed, the faster the cube will move.
Vector3 startPosition = transform.position; //Save the starting position to a different variable so you can reference it later
Vector3 endPosition = startPosition + Vector3.forward; //Vector3.Forward is equivalent to saying (0, 0, 1);
float length = Vector3.Distance(startPosition, endPosition); //You'll need to know the total distance that the cube will move.
while(transform.position != endPosition) //This loop while keep running until the cube reaches its endpoint
{
float distCovered = (Time.time - startTime) * speed; //subtracting the current time from your start time and multiplying by speed will tell us how far the cube's moved
float fraction = distCovered / length; //This will tell us how far along the cube is in relation to the start and end points.
transform.position = Vector3.Lerp(startPosition, endPosition, fraction); //This line will smoothly transition between the start and end points
}
}
I hope this helps you. This is my first time answering a question so sorry if I got some things wrong/it's not the most optimized. Good Luck!

Get position from player forward at constant distance

The simple way to get player front position at specific distance
Vectro3 forward = player.transform.forward * distance;
Vector3 newPlayerFronPosition= player.transform.position + new Vector3(forward.x, forward.y, forward.z);
newPlayerFronPosition= new Vector3(newPlayerFronPosition.x, newPlayerFronPosition.y - 4f, newPlayerFronPosition.z);
navigationCanvas.transform.position = newPlayerFronPosition;
navigationCanvas.transform.rotation = camRotationToWatch.transform.rotation;
its actually working fine but the problem is as my player move up or down the navCanvas become appear ver near to my player. How to mainitain spcific distance all the time.?? that no matter player look above or down the navcanvas display at specfic distance.(position)
disatnceUICam = Vector3.Distance(newPlayerFronPosition, player.transform.position);
I also logged the distance and surprisingly it the distance is changing when i am moving up or down. its changing from 6 to 12 as i am looking up to down.
If I've understood you correctly, and you want a point on in front of your player transform on the X Z Plane a set distance from the forward of your player, you should try something like this:
Vector3 horizontalForward = new Vector3(
player.transform.position.x + player.transform.forward.x,
player.transform.position.y,
player.transform.position.z + player.transform.forward.z
).normalized * distance;
I suspect what you're describing is occurring because the transform of your 'player' variable is connected to the direction of your game camera. As the camera looks up, the world position of your forward changes relative to the camera. Using just the X and Z will produce a varying distance as your camera transform rotates around the X Axis. Perhaps this diagram will illustrate what I mean a little better:
Sorry the hypotenuse is a little wonky but you get the idea right?

ball reflection angles Xna c#

I'm trying to find a way to handle reflections for a breakout clone.
I would upload an image to the post instead of the following paragraph, however i have not yet gained the privilege of that yet.
If the ball intersects the left hand side i want it to bounce off to the left.
if the ball intersects the right hand side i want it to bounce off to the right. if the ball intersects the middle section i want it to bounce up the way. i want to learn how to make it bounce in a varying direction dependant on what side of the left, right, or middle section was intersected
I would like to not use three separate rectangles for this, i want to learn how to do it with one.
I use a Vector2 for ball velocity, projVel.
It's position is projPos.
A rectangle for the paddle lightRect.
The reason I use proj.collRect for the beginning of the if is because I cannot use the intersect method with Vector2.
This is my makeshift collision handler at present, which does work but the speed changes to an extent which renders the game unplayable. The speed clamp i have only slightly slows it down i think. i have a variable for projSpeed i cannot clamp that or it will never be able to stop.
if (proj.collRect.Intersects(lightSaber.lightRect))
{
proj.projPos.Y = lightSaber.lightRect.Y - proj.projTxr.Height;
proj.projVel.Y *= -1;
proj.projVel.X = 10 * (proj.projPos.X - lightSaber.lightRect.Center.X) / (lightSaber.lightRect.Center.X);
}
proj.projVel.X = Math.Max(-4, Math.Min(proj.projVel.X, 4));
proj.projVel.Y = Math.Max(-4, Math.Min(proj.projVel.Y, 4));
Help me by showing me how I could do this, maybe in the Math. method, or even an alternative to .Intersects so I can use projPos instead of collRect.
I really am not sure where to start, if there is another way I could do it an example would be great.
Instead of manipulating X and Y velocities independently, I recommend that you calculate a reflection angle based on the position and then derive the velocity from the angle and the speed prior to impact.
Example:
// NOTE: this code assumes that positive Y is down
if (proj.collRect.Intersects(lightSaber.lightRect) && projPos.projVel.Y > 0.0f) // only bounce if projectile is moving downward
{
// remember current speed for when we calculate new velocity
var projSpeed = projVel.Length();
// make sure the projectile no longer intersects the bar
proj.projPos = lightRect.Y - proj.projTxr.Height;
// interpolate reflection angle
var t = (proj.projPos.X - lightSaber.lightRect.X) / lightSaber.lightRect.Width;
var reflectDegrees = 150.0f - t * 120f; // straight up +/- 60 degrees
var reflectRadians = reflectDegrees * (float)Math.PI / 180.0f;
// final velocity determined by angle and original projectile speed
proj.projVel = new Vector2((float)Math.Cos(reflectRadians) * projSpeed, -(float)Math.Sin(reflectRadians) * projSpeed);
}

2D Game Physics Vectors issue

I've been working on a simple program in C# in which a Ball [X,Y] cordinates are periodical incremented.
I've managed to implement a collision detection method, but I'm trying to determine how to reflect the ball at an angle oposed bouncing it back along the same linear path.
dx = -dx //This bounces the ball back along the same linear path
dy = -dy
Solution
Trigonometry
theta = range between 0<theta<=360 depending on where it bounced
x = cos(theta)*time
y= sin(theta)*time
The whole point of Newtonian physics is that it is not random, it is deterministic. If you throw the same ball against the same wall at the same angle and with the same velocity and the same spin, it goes to the same place every time.
This sort of program is a really great learning opportunity for both programming and physics. What I encourage you to do is to first write a program that simulates very simple bouncing. As you note, when an object is moving straight down and hits a horizontal surface, then you can model the bounce as simply reversing the vertical velocity component. Just get that right; no gravity, no nothing. That's a great start.
Then try adding bouncing off of horizontal walls, the same way.
Then try adding bouncing off of walls that are not aligned with horizontal or vertical directions. That's where you're going to have to learn how vectors and trigonometry work, because you'll have to work out what component of the ball's velocity is changed by striking the wall obliquely.
Then add gravity. Then add friction from the air. Then add the fact that the ball can be spinning. Add elasticity, so that you can model deformation of the ball.
Once you get to that point, if you want to introduce randomness you'll be able to figure out how to do it. For example, you might introduce randomness by saying "well, when the ball strikes the wall and deforms, I'll introduce a random element that changes its deformation by 0-10%". That will then change how the simulation bounces the ball. You can experiment with different kinds of randomness: add random air currents, for instance.
You will have to add in randomness yourself. To rephrase your question: "Deterministically, it bounces off at angle theta. How can I make it bounce back at angle theta + epsilon, where epsilon is some random value?"
To rotate a vector, see this. You will just specify theta.
pseudocode:
RotateVector(vec):
bounce_vec = [-vec.x vec.y]; //deterministic answer is negative x, normal y
bounce_angle = acos(dot(vec,bounce_vec) / (norm(vec)*norm(bounce_vec)));
modified_angle = bounce_angle + random_number();
ca = cos(modified_angle);
sa = sin(modified_angle);
rotation_matrix = [ca -sa; sa ca];
return rotation_matrix * vec;
Line 3 uses the law of cosines to figure out the angle. In line 4, that angle is modified randomly. The rest of the function rotates the original vector by your new angle.
As long as it's a perfect ball with a perfect surface it will not bounce back randomly. Neither vectors nor trigonometry will give you any randomness.
"randomly, though applying to the basic laws of physics" seems like an oxymoron. However...
If you want it to bounce in a random direction, while maintaining its current speed, you might do something like this (pseudocode):
first, bounce back the canonical way (dx = -dx or dy = -dy depending on the collision)
then convert the dx and dy to polar coordinates (theta and r)
jitter theta by a small amount (+ or - a few degrees, according to your taste)
make sure theta isn't heading into a wall that you just bounced off
convert theta and r back to dx and dy
That would be conserving scalar momentum.

Simple 2D rocket dynamics

I am currently experimenting with some physics toys in XNA using the Farseer Physics library, however my question isn't specific to XNA or Farseer - but to any 2D physics library.
I would like to add "rocket"-like movement (I say rocket-like in the sense that it doesn't have to be a rocket - it could be a plane or a boat on the water or any number of similar situations) for certain objects in my 2D scene. I know how to implement this using a kinematic simulation, but I want to implement it using a dynamic simulation (i.e. applying forces over time). I'm sort of lost on how to implement this.
To simplify things, I don't need the dynamics to rotate the geometry, just to affect the velocity of the body. I'm using a circle geometry that is set to not rotate in Farseer, so I am only concerned with the velocity of the object.
I'm not even sure what the best abstraction should be. Conceptually, I have the direction the body is currently moving (unit vector), a direction I want it to go, and a value representing how fast I want it to change direction, while keeping speed relatively constant (small variations are acceptable).
I could use this abstraction directly, or use something like a "rudder" value which controls how fast the object changes directions (either clockwise or counter clockwise).
What kind of forces should I apply to the body to simulate the movement I'm looking for? Keep in mind that I would also like to be able to adjust the "thrust" of the rocket on the fly.
Edit:
The way I see it, and correct me if I'm wrong, you have two forces (ignoring the main thrust force for now):
1) You have a static "fin" that is always pointed in the same direction as the body. If the body rotates such that the fin is not aligned with the direction of movement, air resistance will apply forces to along the length of the fin, proportional to the angle between the direction of movement and the fin.
2) You have a "rudder", which can rotate freely within a specified range, which is attached some distance from the body's center of mass (in this case we have a circle). Again, when this plane is not parallel to the direction of movement, air resistance causes proportional forces along the length of the rudder.
My question is, differently stated, how do I calculate these proportional forces from air resistance against the fin and rudder?
Edit:
For reference, here is some code I wrote to test the accepted answer:
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
float dc = 0.001f;
float lc = 0.025f;
float angle = MathHelper.ToRadians(45);
Vector2 vel = new Vector2(1, 0);
Vector2 pos = new Vector2(0, 0);
for (int i = 0; i < 200; i++)
{
Vector2 drag = vel * angle * dc;
Vector2 sideForce = angle * lc * vel;
//sideForce = new Vector2(sideForce.Y, -sideForce.X); // rotate 90 degrees CW
sideForce = new Vector2(-sideForce.Y, sideForce.X); // rotate 90 degrees CCW
vel = vel + (-drag) + sideForce;
pos = pos + vel;
if(i % 10 == 0)
System.Console.WriteLine("{0}\t{1}\t{2}", pos.X, pos.Y, vel.Length());
}
}
When you graph the output of this program, you'll see a nice smooth circular curve, which is exactly what I was looking for!
If you already have code to integrate force and mass to acceleration and velocity, then you just need to calculate the individual part of each of the two elements you're talking about.
Keeping it simple, I'd forget about the fin for a moment and just say that anytime the body of your rocket is at an angle to it's velocity, it will generate a linearly increasing side-force and drag. Just play around with the coefficients until it looks and feels how you want.
Drag = angle*drag_coefficient*velocity + base_drag
SideForce = angle*lift_coefficent*velocity
For the rudder, the effect generated is a moment, but unless your game absolutely needs to go into angular dynamics, the simpler thing to do is let the rudder control put in a fixed amount of change to your rocket body angle per time tick in your game.
I suddenly "get" it.
You want to simulate a rocket powered missile flying in air, OK. That's a different problem than the one I have detailed below, and imposes different limits. You need an aerospace geek. Or you could just punt.
To do it "right" (for space):
The simulated body should be provided with a moment of inertia around its center of mass, and must also have a pointing direction and an angular velocity. Then you compute the angular acceleration from the applied impulse and distance from the CoM, and add that to the angular velocity. This allows you to compute the current "pointing" of the craft (if you don't use gyros or paired attitude jets, you also get a (typically very small) linear acceleration).
To generate a turn, you point the craft off the current direction of movement and apply the main drive.
And if you are serious about this you also need to subtract the mass of burned fuel from the total mass and make the appropriate corrections to the moment of inertia at each time increment.
BTW--This may be more trouble than it is worth: maneuvering a rocket in free-fall is tricky (You may recall that the Russians bungled a docking maneuver at the ISS a few years ago; well, that's not because they are stupid.). Unless you tell us your use case we can't really advise you on that.
A little pseudocode to hint at what you're getting into here:
rocket {
float structuralMass;
float fuelMass;
point position;
point velocity;
float heading;
float omega; // Angular velocity
float structuralI; // moment of inertia from craft
float fuelI; // moemnt of inertia from the fuel load
float Mass(){return struturalMass + fuelMass};
float I(){return struturalI + fuelI};
float Thrust(float t);
float AdjustAttitude(float a);
}
The upshot is: maybe you want a "game physics" version.
For reason I won't both to go into here, the most efficient way to run a "real" rocket is generally not to make gradual turns and slow acceleration, but to push hard when ever you want to change direction. In this case you get the angle to thrust by subtracting the desired vector (full vector, not the unit) from the current one. Then you pointing in that direction, and trusting all out until the desired course is reached.
Imagine your in floating in empty space... And you have a big rock in your hand... If you throw the rock, a small impulse will be applied to you in the exact opposite direction you throw the rock. You can model your rocket as something that rapidly converts quantum's of fuel into some amount of force (a vector quantity) that you can add to your direction vector.

Categories