Slowly accelerate and slowly slow down while moving

I really can’t figure how to do this. I tried many ways, drawing on paper, projecting vectors on axis etc.

Here is the deal:

I have a helicopter object. It has some simple AI code I wrote down, and basically, it just picks a random point in the world and flies towards it. Now, I can easily make it accelerate until it reaches some max speed, but how do I make it slow down as it reaches towards it’s destination?

And thats one part of the problem, second part is: how do I get it’s move speed per one axis? The reason I need this for is that helicopters lean as they move and I need to make angle dependant on movespeed per that axis.

I hope I explained my problem well enough.

I use C#, but I’m quite comfortable with JS too so it really doesn’t matter in which language script is written.

EDITED: I changed my previous answer to something more complete (the script I used to test that answer)

You could define a distance value, and decelerate when entering this distance from the target point - by the way, the same trick can be used to accelerate. To lean according to the movement, you can use the current velocity and tilt a vector in its direction, making the helicopter follow this vector:

```using UnityEngine;
using System.Collections;

public class Helicopter : MonoBehaviour {

public float maxVel = 30; // cruise speed
public float startVel = 5; // speed at the starting point
public float stopVel = 0.5f; // speed at the destination
public float accDistance = 20; // acceleration/deceleration distance
public float factor = 0.25f; // max inclination
public float turnSpeed = 0.8f; // speed to turn/bank in the target direction

Vector3 lastPos; // used to calculate current velocity

void Start(){
lastPos = transform.position;
StartCoroutine(Fly()); // demo routine
}

// calculate bank/turn rotation at Update
void Update(){
// calculate the displacement since last frame:
Vector3 dir = transform.position-lastPos;
lastPos = transform.position; // update lastPos
float dist = dir.magnitude;
if (dist > 0.001f){ // if moved at least 0.001...
dir /= dist; // normalize dir...
float vel = dist/Time.deltaTime; // and calculate current velocity
// bank in the direction of movement according to velocity
Quaternion bankRot = Quaternion.LookRotation(dir+factor*Vector3.down*vel/maxVel);
transform.rotation = Quaternion.Slerp(transform.rotation, bankRot, turnSpeed*Time.deltaTime);
}
}

bool flying = false; // shows when FlyTo is running

// coroutine that moves to the specified point:
IEnumerator FlyTo(Vector3 targetPos){
flying = true; // flying is true while moving to the target
Vector3 startPos = transform.position;
Vector3 dir = targetPos-startPos;
float distTotal = dir.magnitude;
dir /= distTotal; // normalize vector dir
// calculate accDist even for short distances
float accDist = Mathf.Min(accDistance, distTotal/2);
do {
float dist1 = Vector3.Distance(transform.position, startPos);
float dist2 = distTotal-dist1;
float speed = maxVel; // assume cruise speed
if (dist1 < accDist){ // but if in acceleration range...
// accelerate from startVel to maxVel
speed = Mathf.Lerp(startVel, maxVel, dist1/accDist);
}
else
if (dist2 < accDist){ // or in deceleration range...
// fall from maxVel to stopVel
speed = Mathf.Lerp(stopVel, maxVel, dist2/accDist);
}
// move according to current speed:
transform.position = Vector3.MoveTowards(transform.position, targetPos, speed*Time.deltaTime);
yield return 0; // let Unity breathe till next frame
} while (transform.position != targetPos); // finish when target reached
flying = false; // shows that flight has finished
}

// example routine: fly to 3 different points in sequence
IEnumerator Fly(){
Vector3 p0 = transform.position;
Vector3 p1 = p0 + new Vector3(150, 0, 200);
Vector3 p2 = p1 - new Vector3(-220, 0, 300);
while (true){
StartCoroutine(FlyTo(p1)); // fly to point 1
while (flying) yield return 0; // wait flight to finish
yield return new WaitForSeconds(5); // rest for 5 seconds
StartCoroutine(FlyTo(p2));
while (flying) yield return 0;
yield return new WaitForSeconds(5);
StartCoroutine(FlyTo(p0));
while (flying) yield return 0;
yield return new WaitForSeconds(5);
}
}

}
```