# How to add deceleration to the ball problem on kinematics

Hi, I’m trying to try make projectiles that targets and launches at the player, and the player has to counter them.

## The Projectiles has three heights: peak height, mid height and the ground height. _ What I want to do is add deceleration to the math for horizontal velocity for peak height, making it go in an arc near the end instead of the middle while heading towards player in a correct spot and not over or under shooting. _ Here is the picture to show how I want the projectile to move, it may not be accurate but it should give a general idea. 199252-deceleration.png1280×720 18.7 KB

I took most of the math from this video:

- The math is about kinematics, here are the equations it uses:
    1. s = ((u + v) * t) / 2
2. v = u + a * t
3. s = u * t + (a * t * t) / 2
4. s = v * t - (a * t * t) / 2
5. v * v = u * u + 2 * a * s

v = final velocity
u = initial velocity
a = acceleration (gravity)
s = displacement
t = duration time


_

Here is the code for the launch function for your perusal.

public float deceleration = 5f;

public float jumpHeight = 2f;

[SerializeField] private bool launchAtAwake;
[SerializeField] private Transform target;

Vector3 LaunchVelocity(Vector2 targetPosition, float heightTarget)
{
float displacementY = heightTarget - rb.heightPosition;
Vector3 displacementXZ = new Vector3(targetPosition.x - rb.groundPosition.x, 0f,
targetPosition.y - rb.groundPosition.y);

float time = Mathf.Sqrt(-2f * jumpHeight / -rb.gravity) +
Mathf.Sqrt(2f * (displacementY - jumpHeight) / -rb.gravity);

Vector3 velocityY = Vector3.up * Mathf.Sqrt(-2f * -rb.gravity * jumpHeight);

// The original Code for horizontal velocity
//Vector3 velocityXZ = displacementXZ / time;

// One of my Attempts for horizontal velocity with deceleration
Vector3 velocityXZ = new Vector3(
Mathf.Sqrt(-2f * -deceleration * Mathf.Abs(displacementXZ.x)), 0f,
Mathf.Sqrt(-2f * -deceleration * Mathf.Abs(displacementXZ.z)));

return velocityXZ + velocityY;
}


_

This is the code for deceleration.

private Vector2 facingVelocity;

void FixedUpdate()
{
float moveSignX = movementSpeed.x != 0f ? Mathf.Sign(movementSpeed.x) : 0f;
float moveSignY = movementSpeed.y != 0f ? Mathf.Sign(movementSpeed.y) : 0f;

rb.groundPosition += new Vector2(moveSignX * facingVelocity.x,
moveSignY * facingVelocity.y) * Time.deltaTime;

if (deceleration > 0)
Accelerate(-deceleration);
}

void Accelerate(float accel)
{
float facingVelX = Mathf.Clamp(facingVelocity.x + accel * Time.deltaTime, 0f, Mathf.Infinity);
float facingVelY = Mathf.Clamp(facingVelocity.y + accel * Time.deltaTime, 0f, Mathf.Infinity);

facingVelocity = new Vector2(facingVelX, facingVelY);
}


_
I’m having a hard time trying to get this problem to work so I’m asking anyone, especially who knows kinematic better then I do, if they know how to solve this math problem.

Thank you.

So yeah, after some looking around, breaking up some problems and a lot of testing, I finally figured it out.
_
This is the formula.

u = 2 * (s / t) - v


Which is similar from this previous formula.

u = s / t


_

This means I can add deceleration to the projectile while still meeting the target, not only that, I can also affect the strength of deceleration, in turn, the shape of the arc in the trajectory by using final velocity.
_
This is my current set-up.

public Vector2 movementSpeed = new Vector2(-5f, 5f);
[Space]

public float decelTime = 1f;

[Range(0f, 1f)] public float decelerationStrength;
private Vector2 finalVelocity;
private Vector2 facingVelocity;
[Space]

public float jumpHeight = 2f;
[Space]

[SerializeField] private bool launchY;
[SerializeField] private bool launchXZ;
[SerializeField] private Transform target;

private Rigidbody3D rb;

void Awake()
{
rb = GetComponent<Rigidbody3D>();
}

void Start()
{
Launch(target.position);
facingVelocity = new Vector2(Mathf.Abs(movementSpeed.x), Mathf.Abs(movementSpeed.y));
}

void FixedUpdate()
{
float moveSignX = movementSpeed.x != 0f ? Mathf.Sign(movementSpeed.x) : 0f;
float moveSignY = movementSpeed.y != 0f ? Mathf.Sign(movementSpeed.y) : 0f;

Accelerate(movementSpeed - finalVelocity, -decelTime);
rb.transform.position += new Vector2(moveSignX * facingVelocity.x, 0f,
moveSignY * facingVelocity.y) * Time.fixedDeltaTime;
}

public void Launch(Vector3 targetPosition)
{
LaunchData ld = CalculateLaunchData(targetPosition);

Vector3 vel = ld.initialVelocity;
decelTime = ld.timeToTarget;
finalVelocity = ld.finalVelocity;

rb.velocity = launchY ? new Vector3(0f, vel.y, 0f) : Vector3.zero;

movementSpeed = launchXZ ? new Vector2(vel.x, vel.z) : movementSpeed;
facingVelocity = new Vector2(Mathf.Abs(movementSpeed.x), Mathf.Abs(movementSpeed.y));
}

LaunchData CalculateLaunchData(Vector3 targetPosition)
{
float displacementY = targetPosition.y - rb.position.y;
Vector3 displacementXZ = new Vector3 (targetPosition.x - rb.position.x, 0,
targetPosition.z - rb.position.z);

float time = Mathf.Sqrt(-2f * jumpHeight  / -rb.gravity) +
Mathf.Sqrt(2f * (displacementY - jumpHeight) / -rb.gravity);

Vector3 velocityY = Vector3.up * Mathf.Sqrt(-2f * -rb.gravity * jumpHeight);

// The original math
//Vector3 velocityXZ = displacementXZ / time;

// The new math
Vector3 finalVelocityXZ = displacementXZ / time * (1f - decelerationStrength);
Vector3 velocityXZ = 2 * (displacementXZ / time) - finalVelocityXZ;

return new LaunchData(velocityXZ + velocityY, finalVelocityXZ, time);
}

void Accelerate(Vector2 speed, float accelTime)
{
Vector2 absSpeed = new Vector2(Mathf.Abs(speed.x), Mathf.Abs(speed.y));

float facingVelX = Mathf.Clamp(facingVelocity.x +
(absSpeed.x / accelTime) * Time.fixedDeltaTime, 0f, Mathf.Infinity);
float facingVelY = Mathf.Clamp(facingVelocity.y +
(absSpeed.y / accelTime) * Time.fixedDeltaTime, 0f, Mathf.Infinity);

facingVelocity = new Vector2(facingVelX, facingVelY);
}

struct LaunchData
{