Projectile Motion in Unity - unity3d

So my friend and I are making some 2D game, we are using some custom character controller, so we are not using rigidbody2D. Now we have some sort of catapult which needs to eject the player in a projectile-motion style.
We've done it for the catapult which shoots the player straight up
In inspector you can decide how much units do you want player to jump and how much does it need to get to reach max height.
So here is the code for the catapult that shoots the player up.
float ejectInicialY = (jumpHeight - ( player.physics.gravity * Mathf.Pow(timeToReachMaxHeight, 2) / 2)) / timeToReachMaxHeight;
float ejectVelocityY = ejectInicialY + player.physics.gravity * Time.deltaTime;
player.physics.playerVelocity = new Vector2(ejectVelocityY, 0f);
I tried to apply the same formulas for the X coordinate, but it doesn't work well.
Any help would be greatly appreciated.

This is ultimately a physics problem.
You are calculating current velocities by determining the acceleration of the object. Acceleration of an object can be determined from the net force acting on the object (F) and the mass of the object (m) through the formula a = F / m. I highly recommend reading some explanations of projectile motion and understanding the meaning of the motion equations you are using.
Vertical Direction
For the vertical direction, the net vertical force during the jump (assuming no air drag, etc.) is player.physics.gravity. So you apply your motion formulas assuming a constant acceleration of player.physics.gravity, which you've seemed to have accomplished already.
Horizontal Direction
Becausegravity does not commonly act in the horizontal direction, the net horizontal force during the jump (assuming no air drag, etc.) is 0. So again you can apply your motion formulas, but this time using 0 as your acceleration. By doing this, you should realize that velocityX does not change (in the absence of net horizontal force). Therefore the X coordinate can be determined through (in pseudo-code) newPositionX = startPositionX + Time.deltaTime * velocityX

Related

Relative sizes of pymunk forces

In Pymunk, is the magnitude of gravity the same as the magnitude of apply_force_at_local_point or apply_force_at_world_point, relatively speaking. In other words, is the magnitude of gravity=(20,40) equal to the magnitude of apply_force_at_world_point((20,40),object's position).
I used the equation of motion, final position = initial position + intial velocity * time + 1/2 * acceleration * t^2, to test that. It turns out that these magnitudes are not equal. For instance, it took a force of (0,-7888) to equal gravity of (0,-1750).
I am trying to determine apply_force_at_world_point force that would equal/cancel out gravity. I know I can just set the body's gravity to zero to achieve that effect but my goal is to determine magnetic force that would be enough to levitate a magnet of given weight and magnetic strength.
How can I find the magnitude of force (without testing a bunch of random values) that would equal gravity.
I hope the information given is enough to understand the issue
You can see how the velocity of a body is updated in the Chipmunk source code: https://github.com/viblo/Chipmunk2D/blob/master/src/cpBody.c#L501
body->v = cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt));
Translated to Python/Pymunk this would be something like this:
body.velocity = body.velocity * damping + (gravity + body.force / body.mass) * dt
From this I think this should work to make a opposing force matching the gravity:
body.apply_force_at_local_point(-space.gravity * body.mass)
(I tested this in a simple simulation with some gravity and a ball shape/body and it seems to work as expected, instead of falling the ball stayed put)

Projectile Physics?

What is the ideal way to implement projectile physics, like a cannonball or arrow? I've been experimenting with BodyForce / BodyVelocity but those look like they're applying a constant, non-diminishing force / velocity to the projectile which doesn't look realistic. I've also just set the Velocity property of the projectile directly which works better, but I'm assuming there's a standard pattern used for something like this.
In physics, velocity is split into 2 components, the vertical component and the horizontal component. When a projectile is in motion through the air, we don't consider air resistence affecting its speed, as it's such a minute force.
Since velocity is split into 2 components, if velocity changes or is applied horizontally, that horizonal velocity or force does not affect the vertical force or velocity, and vice versa. This is why projectiles travel at a constant speed horizontally. The vertical velocity, however, is not constant. Due to gravity, the projectile will fall to the earth faster over time. This is acceleration.
What you could try is to add a body velocity with a high value, such as 400,400,0: a velocity for the x, y and z axis, and then immediately remove the velocity a fraction of a second later. What this does is creates an initial velocity, which eventually gets changed by gravity on the y component.
To learn more about projectile physics, you can check out online resources such as the following:
http://bowlesphysics.com/images/AP_Physics_B_-_Projectile_Motion.pdf

Camera: "Linear" zoom

I want to move a camera closer to an object in Unity, so that the zooming is linear. Take a look at the zooming in the Scene window in the Unity Editor. The camera isn't moving with a constant speed. The more zoomed in you are, the slower the camera moves. And I do want to move the camera, I don't want to change the FOV.
First off, yes do not use the FOV to do that, it would be a massive pain to control the movement. Being in low FOV, would mean you are focus on a tiny part and movement would be hard to control since one unit would be a large movement in small FOV. Also, a large FOV creates fish eye effect. So nope.
One way you could achieve this fast to slow effect is to use a distance to define the amount of movement
Let's consider you use the mouse wheel to zoom in and out, you listens to the value and create a movement based on that.
float movement = Input.GetAxis("Mouse ScrollWheel");
if(movement == 0)
{
return;
}
Transform camTr = Camera.main.transform;
float distance = Vector3.Distance(camTr.position, origin.position) + 1;
camTr.Translate(camTr.forward * distance * movement * Time.deltaTime * speed);
speed variable is meant to control how fast regardless of the distance. Distance gets a plus 1 so you can still move while real close to the origin.
The origin position needs to be defined, it could be based on a raycast going forward from the camera and hitting at y = 0. Just an idea. It could also be a focused object, that all depends on what you are doing.
The whole point here is that your camera will move faster if you are far from the focus point. Also, you may want to clamp the movement so that begin far away does not result in gigantic movement.
i propose you to use FOV (because player feel good)
1- use Transform.localPosition to change distance of camera to near or far - you should change z axis to changing distance of camera
2- use camera rendertotexture and in GUI change scale of it ( isn't good because need pro unity license and get allot of memory);
but can't know whats reason for you want forget changing FOV
One step of perspective projection of a point is the division by distance of that point. This means that the projected size of any object does not change linearly with its distance.
projectedSize = originalSize / distance
So if you want to approach an object in a way that its projected size grows linearly, you'll have to change your distance non-linearly.
We do this by also dividing the distance by some value f. The exact value of f depends on the stepSize and (I think) the FoV of your camera.
By using FixedUpdate() instead of Update() we make sure we have a constant stepSize which allows us to assume f as being constant as well.
void FixedUpdate()
{
newDistance = oldDistance / f;
}
For the definition of f you can use any value bigger than, but close to 1. For example f = 1.01f. This will approximate the desired behaviour quite well. If you want it to be perfectly linear, you'll have to dig deeper into the calculations behind perspective projection and calculate the exact value of f yourself: https://en.wikipedia.org/wiki/3D_projection#Perspective_projection

How does SpriteKit physics move bodies?

How does SpriteKit's physics engine (Box2d) move bodies and apply gravity to them?
is it just the standard:
velocity = velocity + gravity
position = position + velocity * deltaTime
or is there a more complex equation.
I ask this because I am trying to calculate the trajectory of the body and plot it.
Simplified, this is correct. However there can be other forces acting on a body (collisions, joints) and thresholds (ie stop moving if velocity below threshold, etc) and floating point rounding errors can add up.
So if you're looking for a forward calculation it depends on how precise it needs to be.
The most precise option would be to actually run the simulation to advance it to see where bodies will be - however since SK doesn't give you the Box2D sources this can't be done, ie you can't copy the world state and advance it manually in a copy of the current world.

How many pixels is an impulse in box2d

I have a ball that you blow on with air. I want the ball to be blown more if it is close to the blower and blown less if it is farther away from the blower. I am using box2d and I am using the impulse function."body->ApplyLinearImpulse(force, body->GetPosition())". I can't seem to find a formula or a way to accomplish this. If I want the ball to blow to a total distance of 300 pixels right, how could I accomplish this? Please help.
If you want to calculate the distance before simulation you have to take a look at box2d sources. When simulating the velocity of the body is modified according to gravity, extra applied forces, linear damping, angular damping and possibly something more. Also velocity relies on velocity iterations.
But I think if you want a really smooth motion (like from a blow) you'd better use applyForce function instead of impulse. But be sure you are applying the force each simulation step.
EDIT:
Also you can simulate the air resistance as:
Fa = -k*V*V. I've simulated movement in the pipe this way. Worked great.
So each step you can make something like this:
BlowForce = k1 / distance; // k1 - coefficient
Resistance = -k2 * V * V; //k2 - another coefficient
TotalForce = BlowForce + Resistance;
body->ApplyForce(TotalForce);
I am not a box 2d expert but what i would do is create a small box which is actually invisible and let the ball hit the box...if the blower is blowing more i would give more speed to the box in opposite direction. As far as 300 pixel length is concerned you have to adjust the forces and velocity such that the ball goes
300/<your_rendering_window_to_physics_world_ratio>
in physical world.
Force = mass * acceleration, so take the mass you set your body to, calculate the acceleration you want (remember to divide 300px by PTM_RATIO) and then multiply the two together.