Calculating 2D parabolic trajectory for a projectile to hit a position - unity3d

I'm developing a Tower defense in 2D in Unity.
I'm trying to calculate a parabola to draw the trajectory of the projectiles fired from a tower in the game. I've got the position of the tower and the position of the enemy - now I need an algorithm that calculates a parabola that will hit the enemy.
Is there a universal algorithm or something like that for this kind of calculation?

Assuming gravity but no drag we have:
where
x, y is displacement
x_0, y_0 is initial location
u_x, u_y is initial velocity
g is acceleration due to gravity
t is time elapsed

Related

Moving a 2D physics body on a parabolic path with initial impulse in unity

What I have:
A projectile in Unity 5 2D, affected by gravity, that I want to move from point A to point B with initial impulse on a parabolic path
What I know:
The 2D coordinates of a random starting position (A)
The 2D coordinates of a random target position (B)
The time (X) I want the body to reach the target position after
What I want to know:
The initial impulse (as in unity applyforce with forcemode impulse) that I have to apply to the body onetime in order for it to reach the desired position B after X time.
Notes:
It is a 2D world using Unity 2D physics
The two positions A and B are totally random and may or may NOT be at equal heights (y coordinates)
I want to apply the impulse one time only when spawning the projectile
The projectile does NOT have any other forces affecting him other than GRAVITY (for the current problem lets assume that it always with magnitude 9.8 pointed down)
Here is a (bad) drawing of what I want :D
Thanks upfront guys!
Let's solve a few simpler problems. Our goal is to find an initial velocity for the particle, instead of an "impulse", because we'll achieve better control this way.
First, consider how we would solve this without Unity physics. A particle's position as a function of time depends on its initial position, velocity and acceleration. The same equations apply regardless of how many dimensions you have. This equation is:
current_position = 1/2 * acceleration * time^2 + velocity * time + starting_position
Let current_position be our desired destination, time be the duration of travel you choose, and the starting_position to be the starting position of the particle.
In the x-dimension, there is no acceleration. Let X_0 be our starting X position, X_1 be our destination, and T be the duration of time we want to spend getting to that destination. We want to find v_x, or the velocity in the x-dimension. For ease of interpretation, I've marked all the constants in uppercase and the variable in lowercase.
X_1 = v_x*T + X_0
v_x = (X_1-X_0)/T
In the y-dimension, we have gravity of some kind. So let's incorporate that as our acceleration:
Y_1 = 0.5*G*T*T + v_y*T + Y_0
v_y = (Y_1 - Y_0 - 0.5*G*T*T)/T
Now that you have v_x and v_y, just set the velocity:
rigidbody2d.velocity = new Vector2(v_x, v_y);
Since different objects have different mass, you don't want to try to calculate an impulse. Just set the velocity to what you want in the frame when the object is spawned.
This runs contrary to advice you might find elsewhere on the Internet, but try it first before doing something more complicated.
Some important notes:
Physics processing in Unity isn't stable: you might get different results on different platforms, especially between different mobile devices. If there is performance pressure, there may be fewer physics evaluations and therefore incorrect results. This is generally not a problem with 2D physics.
You may experience an issue with the scale of gravity, depending on your version and what other settings you have.
The formulas of position of a projectile influenced only by gravity are these:
x = x0 + v_x0*t
y = y0 + v_y0*t + 0.5*g*t^2
so, to know the starting velocity, with some basic calculations:
v_x0 = (x-x0)/t
v_y0 = (y-y0)/t + 0.5*g*t^2/t = (y-y0)/t - 4.9*t
Now, in order to add this startin velocity by using AddForce, we could have used ForceMode.VelocityChange, but this mode is only available for 3D rigidbodies, so we need to use the ForceMode.Impulse and multiplying the force by the mass of the object:
RigidBody2D rigid = GetComponent<RigidBody2D>();
rigid.AddForce(new Vector2 (v_x0, v_y0) * rigid.mass, ForceMode2D.Impulse);
and that's it.
Of course you can just set the velocity of the rigid body directly instead of using AddForce.

Unity - Matching Speed While Transistioning From Traveling on a Single Axis to Rotation Around a Circle

I am working on a simple project that consists of a ball with a rigid body being pushed along the x axis. The ball needs to transition 90 degrees and continue straight up.
I've created a box to serve as a pivot/rotation point and placed it exactly 5 units above the beginning of the 90 degree transition from and exactly 5 units away from the end of the transition. I've created two colliders that work as triggers; one at the beginning and one at the very end of the 90 degree transition.
So my ball will come zooming along on the x axis and hit the first trigger. When it does I reset the ball's velocity to zero and parent the ball to the box serving as a pivot/rotation point. I've then applied angular velocity to the box so that the ball will rotate exactly 5 units around the pivot point. When the ball hits the second collider at the end of the transition it is un-parented and velocity is reapplied so the ball can continue straight up.
So here is the question; if the ball is 5 units away from the pivot point, the distance traveled for the 90 degree transition would be something like : 5 * 2 = the circles diameter * PI = 31.4 units distance around the circle / 4 = 7.84 game units to travel for the entire 90 degree transition.
So how do I match the velocity the ball had while traveling solely on the x axis so that it has the same speed while transitioning using the pivot point rigid body's moveRotation function around a circular axis?
If I have a velocity vector of (-10, 0, 0) when I hit the first trigger how do I calculate what to feed into the moveRotation function so that a the ball, rotating 5 units away from the pivot point, is still traveling at 10 units a second?
Taking the original velocity (-10, 0, 0) and multiplying by the distance needed to travel for the 90 degree transition(7.85 units) looks really close but I can figure out how to check it.

Unity3D relative rotation of objects on an axis

In the project I am using IMU sensors to track real player's hand and apply the transformation values onto 3D hand inside Unity.
As IMU sets the Y axis orientation relative to magnetic north of the earth, in the game, hand initializes on specific direction.
What I want is to calculate the offset of IMU's given Y values and 3D hand's original Y rotation, so that I can subtract that value to the 3D model's Y rotation (that will seem like player's initial Y Rotation is the same as 3D hand's). Code would be: transform.Rotate(Vector3.up, offset, Space.World);
IMU sends Euler angles (does it well, as I wasn't able to get Gimbal lock)
As I understand, I need to find out angle difference between 3D Hand's initial rotation and IMU's given initial rotation on XZ plane (or through Y Axis)
How do I calculate the offset?
You can use Quaternion.FromToRotation to calculate offset, something like:
var offset = Quaternion.FromToRotation(Vector3.up, imuUp);
transform.rotation *= offset;

Projectile motion of a cannon ball with air drag and air density not correct plot?

I am trying to write a matlab code to model the projectile motion of a cannon shell including the effects of air drag and air density that changes with respect to temperature, however the code I have so far only computes a straight line for the shell trajectory which is incorrect. Can anyone point out where I have gone wrong and point me in the right direction to include the effect of air density and temperature? Thanks.
clear;
%input parameters
v0=input('Enter the muzzle velocity (m/s) ');
theta=input('Enter the quadrant elevation (degrees) ');
%T0=input('Enter the value for the ground temperature in degreees ');
%T0=T0+275.16;
b2bym0=4e-5;
g=9.8;
dt=1e-2;
%define initial conditions
x0=0;
y0=0;
vx0=v0*cosd(theta);
vy0=v0*sind(theta);
fdragx=-b2bym0*v0*vx0;
fdragy=-b2bym0*v0*vy0;
n=1000; %iterations
%Tratio=(T0/300)^(2.5);
%define data array
%t=zeros(1000);
x=zeros(1000); %x-position
y=zeros(1000); %y-position
vx=zeros(1000); %x-velocity
vy=zeros(1000); %y-velocity
for i=1:n
t(i)=i*dt;
vx(i)=vx0+fdragx*dt;
vy(i)=vy0+fdragy*dt;
x(i)=x0+vx(i)*dt;
y(i)=y0+vy(i)*dt;
x0=x(i);
y0=y(i);
vx0=vx(i);
vy0=vy(i);
end
plot(x,y,'g+')
it doesn't look like you are modeling the downward acceleration of g force for your y velocity
Looks like there were three issues.
First you missed gravity in updating vy. Fixed
Second drag force was not updating with the velocity. Fixed
Thirdly, your calculating the new position/velocities using the initial values and not the previous ones. In the loop try changing these lines. You might have to update your for loop to go from 2:n if matlab indexes at 1.
vx(i)=vx(i-1)+fdragx*dt;
vy(i)=vy(i-1)+(-g+fdragy)*dt;
x(i)=x(i-1)+vx(i)*dt;
y(i)=y(i-1)+vy(i)*dt;
Edit:
Didnt see the update of the initial conditions, disregard the third comment.

Detecting the direction of the accelerometer movement on the y axis

I currently detect movement on the y axis. How does one calculate the direction it moved on the axis?
I get the same values when moving up or down.
Is the Gyro needed for this?
Do remember that the accelerometer will reflect the force of gravity. So movement up and down will generally be reflected as 9.81 m/s2 plus or minus the actual acceleration of the device relative to the Earth.