Распространяющаяся кривая по осям x-y

#c# #unity3d

Вопрос:

Для отправки снаряда в моей игре у меня есть функция кривой в 3D-пространстве, где кривая распространяется по оси z в соответствии с уравнением:

 x = this.LinePoints[t - 1].x   xOffset;
y = this.LinePoints[t - 1].y   yOffset;
z = t == 1 ? 0.35f : math.cos(scaleFactor * (t * 0.1f)) * (t * 0.5f);
 

где t идет от 1 до 40, а точки линий-это линия (x, y), идущая от начальной точки к конечной точке.

Мне нужно распространить кривую вдоль комбинации осей x и y от начальной точки до конечной точки (сохраняйте те же функции, но «поворачивайте» ее, чтобы кривая была включена (x, y)).

Как я могу это сделать?

Комментарии:

1. Прямая ли линия, описываемая точками линий? Что вы подразумеваете под «поворотом» кривой — как вы хотите, чтобы выглядела 2D-траектория? Вы имеете в виду, что хотите, чтобы снаряд прошел между двумя заранее определенными точками с формулой оси Z, примененной в качестве «модификатора» угла?

2. Спасибо за вашу поддержку, да, это линия из 40 точек, идущая от начальной точки (x0, y0, 0) до конечной точки (x1, y1, 0). Я хочу, чтобы полученная кривая находилась на плоскости (x, y) (z = 0).

Ответ №1:

Давайте разделим проблему на три части:

1. Заставить снаряд следовать по линиям

Все достаточно просто. Просто добавляйте this.LinePoints[t - 1] - this.LinePoints[t - 2] transform.position , когда хотите, чтобы снаряд двигался вперед.

 void FixedUpdate() {
    float xDiff = LinePoints[t - 1].x - LinePoints[t - 2].x;
    float yDiff = LinePoints[t - 1].y - LinePoints[t - 2].y;

    transform.position  = new Vector2(xDiff, yDiff);
    t  ;
}
 

2. Добавление кривой по оси Z без поворота

Нам нужно определить функцию для кривой оси Z и просто применить ее поверх оси Y.

 void FixedUpdate() {
    float zDiff = ZFunction(t) - ZFunction(t - 1);

    float xDiff = LinePoints[t - 1].x - LinePoints[t - 2].x;
    float yDiff = LinePoints[t - 1].y - LinePoints[t - 2].y   zDiff;

    transform.position  = new Vector2(xDiff, yDiff);
    t  ;
}

float ZFunction(int t) {
    if (t == 1) {
        return 0.35f;
    }
    else {
        return Mathf.Cos(scaleFactor * (t * 0.1f)) * (t * 0.5f);
    }
}
 

Это будет работать нормально, если значение Y начальной и конечной точек будет одинаковым.

3. Поворот кривой по оси Z

Нам нужно сначала получить угол между точками, а затем получить элементы X и Y вращения под определенным углом. Элемент X угла равен cos(angle) , а элемент Y равен sin(angle) . Умножьте значение Z-функции на тригонометрическую функцию для противоположной оси, а затем добавьте ее поверх позиции.

Вы можете получить угол с помощью Vector2.Angle() , просто не забудьте преобразовать его в радианы, чтобы его можно было использовать с помощью Mathf тригонометрических функций.

 void FixedUpdate() {
    float angle = Vector2.Angle(startPoint, endPoint) * Mathf.Deg2Rad;
    float zDiff = ZFunction(t) - ZFunction(t - 1);

    float xDiff = LinePoints[t - 1].x - LinePoints[t - 2].x   zDiff * Mathf.Sin(angle);
    float yDiff = LinePoints[t - 1].y - LinePoints[t - 2].y   zDiff * Mathf.Cos(angle);

    transform.position  = new Vector2(xDiff, yDiff);
    t  ;
}

float ZFunction(int t) {
    if (t == 1) {
        return 0.35f;
    }
    else {
        return Mathf.Cos(scaleFactor * (t * 0.1f)) * (t * 0.5f);
    }
}
 

Примечание: Если вам не нужны конкретные точки LinePoints , вам, вероятно, следует удалить массив и динамически получить соответствующие позиции. Я бы рекомендовал разобраться Vector2.Lerp() или даже лучше заняться математикой самостоятельно.

Код очень грубый и непроверенный, поэтому прокомментируйте, если у вас возникнут какие-либо проблемы.