Як зробити так, щоб лінії Line Renderer залишалися рівними?


10

Я помітив, що в міру додавання більшої вершини до рядка рендерінга лінія скручується і перестає бути гладкою.

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

.GIF Тут: http://i.imgur.com/hRAhCXM.gif

Усі лінії знаходяться на одному рівні z, навіть якщо я видаляю матеріали, лінії, як здається, скручуються.

Я не маю поняття, чому це робиться, або як можна вирішити це, будь-які пропозиції? C #


Це проблема з алгоритмом, який LineRenderer використовує для позиціонування своїх вершин, який погано має справу з гострими кутами. Ви можете дещо покращити його, додавши більше точок, щоб закруглити кути, але найбільш надійний метод, який я знайшов, - це дублювати його функціональність для кращого алгоритму, створюючи динамічну Mesh з потрібними вершинами, або творчо використовуючи 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 так, як вони це зробили, тому що, роблячи це таким чином, можна уникнути іншої проблеми, куточків. Коли ви почнете малювати кожен сегмент рядка, ви почнете бачити, де два сегментних рядків збираються разом і утворюють потворний стик. Існують способи впоратися з цим, обчисливши загальну нормальну між обома лініями та оновивши їх вершини до спільної нормальної, але це лише частково вирішує проблему, оскільки ви все ще можете легко закінчити стисканими рядками. Найбільш надійне рішення - генерувати додаткові вершини на місцях стиків, щоб вони виконували роль кутів.


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


0

Я уникав цього, це те, що я завжди встановлював позицію z на 0 у методі LineRenderer.SetPosition (). Тож замість того, щоб писати

LineRenderer.SetPosition(i, myVector3);

я написав

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

Але це не найкраще рішення, оскільки ви все одно отримаєте ці дивні лінії. Найкращим рішенням, про який я міг придумати, було створення окремих ліній. Це прекрасно працювало для мене. Сподіваюся, що це вам допоможе.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.