Как сделать так, чтобы линии Line Renderer оставались плоскими?

10

Я заметил, что когда я добавляю больше вершин в линию рендерера линий, линия скручивается и перестает быть гладкой линией.

введите описание изображения здесь

.GIF Здесь: http://i.imgur.com/hRAhCXM.gif

Все линии находятся на одном и том же уровне z, даже если я удаляю материалы, линии, кажется, все еще искривляются.

Я понятия не имею, почему это происходит, или как решить эту проблему, какие-либо предложения? C #

Дуглас Гаскелл
источник
Это проблема с алгоритмом, который LineRenderer использует для позиционирования своих вершин, который плохо работает с острыми углами. Вы можете немного улучшить его, добавив больше точек, чтобы закруглить углы, но самый надежный метод, который я нашел, - это продублировать его функциональность для себя с помощью лучшего алгоритма, создав динамическую сетку с нужными вам вершинами, или творчески используя ParticleSystem, чтобы нарисовать цепочку точек.
DMGregory
1
Обновление: в более поздних версиях Unity (5 + 5) улучшен алгоритм LineRenderer , поэтому пользователи, рассматривающие возможность использования LineRenderers, могут обнаружить, что готовый результат значительно лучше в наши дни.
DMGregory

Ответы:

11

Проблема в основном это:

введите описание изображения здесь

LineRenderer пытается соединить красные точки. Это создание зеленых вершин для создания сетки. Так что сегмент верхней линии выглядит великолепно. Но тогда LineRenderer пытается быть экономным, он использует вершины от конца одного отрезка в конце второго отрезка. Когда есть острый угол, вы получаете проблему, которую видите. Второй отрезок линии зажимается на пересечении, потому что его «концевая заглушка» не перпендикулярна другой «концевой заглушке».

Решение состоит в том, чтобы создать свой собственный рендер, а не сделать его таким экономичным. Вы можете сделать это, создав динамическую сетку . Сетка будет состоять из серии тонких четырехугольников. Для каждого отрезка линии вы можете вычислить четыре угла четырехугольника, вычислив нормаль линии и заданную ширину линии:

Vector3 normal = Vector3.Cross(start, end);
Vector3 side = Vector3.Cross(normal, end-start);
side.Normalize();
Vector3 a = start + side * (lineWidth / 2);
Vector3 b = start + side * (lineWidth / -2);
Vector3 c = end + side * (lineWidth / 2);
Vector3 d = end + side * (lineWidth / -2);

Здесь a, b, cи dсоставляет четыре угла одного сегмента линии, так же как и зеленые точки на изображении выше. Эти вершины будут добавлены в сетку, и вы также добавите индексы, чтобы превратить четыре вершины в два треугольника (таким образом, будет добавлено шесть индексов, abc и bdc).

Это, очевидно, может быть довольно сложным. Я полагаю, что еще одна причина, по которой Unity реализовал свой LineRenderer так, как они это сделали, заключалась в том, что это было сделано, чтобы избежать другой проблемы - углов. Когда вы начнете рисовать каждый отрезок линии, вы увидите, где два отрезка соединяются и образуют некрасивое соединение. Есть способы справиться с этим, рассчитав общий нормаль между обеими линиями и обновив их вершины до общего нормального значения, но это только частично решает проблему, так как вы все равно можете легко получить сжатые линии. Наиболее надежным решением является создание дополнительных вершин в соединениях, которые будут выступать в качестве углов.

MichaelHouse
источник
1
Вы также можете избежать использования средства визуализации единой линии и вставки дополнительных точек для создания небольшой метрики. Просто поставьте точку немного ближе к следующей точке от предыдущей точки.
mklingen
Отличное объяснение Байт, спасибо. Я, наверное, попробую и посмотрю, не смогу ли я заработать больше очков в каждом из углов, если это не сработает, я попробую создать динамическую сетку. Спасибо.
Дуглас Гаскелл
1

У меня была та же проблема, и я решил ее, добавив больше точек к сглаженным краям, это не элегантное решение, а простое и работающее. По крайней мере для меня. Я написал функцию для этого:

Vector3[] Generate_Points(Vector3[] keyPoints, int segments=100){
    Vector3[] Points = new Vector3[(keyPoints.Length - 1) * segments + keyPoints.Length];
    for(int i = 1; i < keyPoints.Length;i++){
        Points [(i - 1) * segments + i - 1] = new Vector3(keyPoints [i-1].x,keyPoints [i-1].y,0);
        for (int j = 1;j<=segments;j++){
            float x = keyPoints [i - 1].x;
            float y = keyPoints [i - 1].y;
            float z = 0;//keyPoints [i - 1].z;
            float dx = (keyPoints [i].x - keyPoints [i - 1].x)/segments;
            float dy = (keyPoints [i].y - keyPoints [i - 1].y)/segments;
            Points [(i - 1) * segments + j + i - 1] = new Vector3 (x+dx*j,y+dy*j,z);
        }
    }
    Points [(keyPoints.Length - 1) * segments + keyPoints.Length - 1] = new Vector3(keyPoints [keyPoints.Length-1].x,keyPoints [keyPoints.Length-1].y,0);
    return Points;
}
Мигель Анхель Льоренте
источник
0

Один из способов решить эту проблему для непрозрачных линий - это нарисовать окружность на каждом стыке. Круг должен иметь диаметр, равный ширине линии. Это требует нескольких дополнительных вершин для рендеринга, но выглядит действительно красиво. Вы также можете избавиться от общих норм между суставами.

Это все еще требует, чтобы вы написали свой собственный код рендеринга вместо использования Unity Line Renderer.

Я сделал актив, который делает это на http://u3d.as/nFE

jjxtra
источник
0

Чтобы избежать этого, я всегда устанавливаю позицию z в ​​0 в методе LineRenderer.SetPosition (). Так что вместо того, чтобы писать

LineRenderer.SetPosition(i, myVector3);

я написал

LineRenderer.SetPosition(i, new Vector3(myVector3.x, myVector3.y, 0));

Но это не лучшее решение, так как вы все равно получите эти странные строки. Лучшее решение, о котором я мог подумать, - это создание отдельных строк. Это отлично сработало для меня. Надеюсь, это поможет вам.

Alexionder
источник