I have some units shooting arrows, right now they move in a straight line to the target. I want them to move like a real arrow, i.e using a parabola curve. However I don't want to use physics.

The math I need to do seems to be beyond me, I've tried to convert 2d solution I found online and other semi-similar solution with no luck.

My current straight movement:

private void Update()
    var nextPos = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
    transform.LookAt(nextPos, transform.forward);
    transform.position = nextPos;

    if (Vector3.Distance(nextPos, target) < .1f)

An example of a 2d version I tried to replicate: Here.

  • \$\begingroup\$ You can use Quadratic Bezier curves to add a parabolic path to your projectiles. They are really easy to understand. You can find a really good tutorial here. The tutorial also provides the link to all the source code in the description. \$\endgroup\$ Jun 14, 2020 at 12:09

1 Answer 1

public float speed;
public Vector3 target;
public float arcHeight;

Vector3 _startPosition;
float _stepScale;
float _progress;

void Start() {
    _startPosition = transform.position;

    float distance = Vector3.Distance(_startPosition, target);

    // This is one divided by the total flight duration, to help convert it to 0-1 progress.
    _stepScale = speed / distance;

void Update() {
    // Increment our progress from 0 at the start, to 1 when we arrive.
    _progress = Mathf.Min(_progress + Time.deltaTime * _stepSize, 1.0f);

    // Turn this 0-1 value into a parabola that goes from 0 to 1, then back to 0.
    float parabola = 1.0f - 4.0f * (_progress - 0.5f) * (_progress - 0.5f);

    // Travel in a straight line from our start position to the target.        
    Vector3 nextPos = Vector3.Lerp(_startPosition, target, progress);

    // Then add a vertical arc in excess of this.
    nextPos.y += parabola * arcHeight;

    // Continue as before.
    transform.LookAt(nextPos, transform.forward);
    transform.position = nextPos;

    // I presume you disable/destroy the arrow in Arrived so it doesn't keep arriving.
    if(progress == 1.0f)
  • 1
    \$\begingroup\$ Works perfectly, thank you, learned a lot from the comments! \$\endgroup\$
    – Majs
    Jun 14, 2020 at 14:31
  • \$\begingroup\$ For anyone coming back here in the future, in order to alter the arc height depending on distance (longer distance = higher arc) I simply add arcHeight = arcHeight * distance; where arcHeight has a value between 0 and 1. \$\endgroup\$
    – Majs
    Jun 14, 2020 at 15:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .