Wie können Line Renderer-Linien flach bleiben?

10

Ich habe festgestellt, dass sich die Linie beim Hinzufügen weiterer Scheitelpunkte zu einer Linienrenderer-Linie verdreht und nicht mehr glatt ist.

Geben Sie hier die Bildbeschreibung ein

.GIF Hier: http://i.imgur.com/hRAhCXM.gif

Alle Linien sind auf der gleichen z-Ebene, auch wenn ich die Materialien entferne, scheinen sich die Linien immer noch zu verdrehen.

Ich habe keine Ahnung, warum dies der Fall ist oder wie ich es lösen soll. Irgendwelche Vorschläge? C #

Douglas Gaskell
quelle
Dies ist ein Problem mit dem Algorithmus, mit dem der LineRenderer seine Scheitelpunkte positioniert, der mit scharfen Ecken schlecht umgeht. Sie können es etwas verbessern, indem Sie mehr Punkte hinzufügen, um die Ecken abzurunden. Die robusteste Methode, die ich gefunden habe, besteht darin, die Funktionalität für sich selbst mit einem besseren Algorithmus zu duplizieren, indem Sie ein dynamisches Netz mit den benötigten Scheitelpunkten erstellen oder kreativ Ausnutzen eines Partikelsystems zum Zeichnen der Punktekette.
DMGregory
1
Update: Spätere Versionen von Unity (5 5+) haben den LineRenderer-Algorithmus verbessert , sodass Benutzer, die LineRenderer verwenden möchten, das Out-of-the-Box-Ergebnis heutzutage möglicherweise wesentlich besser finden.
DMGregory

Antworten:

11

Das Problem ist im Grunde das:

Geben Sie hier die Bildbeschreibung ein

Der LineRenderer versucht, die Positionen der roten Punkte zu verbinden. Es werden die grünen Eckpunkte erstellt, um ein Netz zu erstellen. Das Top-Line-Segment sieht also gut aus. Aber dann versucht der LineRenderer wirtschaftlich zu sein, er verwendet die Eckpunkte vom Ende eines Liniensegments am Ende des zweiten Liniensegments wieder. Wenn es einen scharfen Winkel gibt, bekommen Sie das Problem, das Sie sehen. Das zweite Liniensegment wird an der Kreuzung eingeklemmt, weil seine "Endkappe" nicht senkrecht zu seiner anderen "Endkappe" ist.

Die Lösung besteht darin, einen eigenen Linienrenderer zu erstellen und diesen nicht so wirtschaftlich zu gestalten. Sie können dies tun, indem Sie ein dynamisches Netz generieren . Das Netz besteht aus einer Reihe dünner Quads. Für jedes Liniensegment können Sie die vier Ecken des Quadrats berechnen, indem Sie die Normalen der Linie und eine bestimmte Linienbreite berechnen:

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);

Hier a, b, cund ddie vier Ecken eines einzelnen Liniensegment bilden, ebenso wie die grünen Punkte im Bild oben. Diese Scheitelpunkte würden dem Netz hinzugefügt, und Sie würden auch die Indizes hinzufügen, um die vier Scheitelpunkte in zwei Dreiecke zu verwandeln (also würden sechs Indizes hinzugefügt, abc und bdc).

Dies kann offensichtlich ziemlich komplex werden. Ich glaube, ein weiterer Grund, warum Unity ihren LineRenderer so implementiert hat, war, dass auf diese Weise ein weiteres Problem vermieden wird, nämlich Ecken. Wenn Sie mit dem Zeichnen jedes Liniensegments beginnen, sehen Sie, wo die beiden Liniensegmente zusammenkommen und eine hässliche Verbindung bilden. Es gibt Möglichkeiten, damit umzugehen, indem Sie die gemeinsame Normalen zwischen beiden Linien berechnen und ihre Scheitelpunkte auf die gemeinsame Normalen aktualisieren. Dies löst das Problem jedoch nur teilweise, da Sie immer noch leicht eingeklemmte Linien erhalten können. Die robusteste Lösung besteht darin, zusätzliche Eckpunkte an den Gelenken zu erzeugen, die als Ecken dienen.

MichaelHouse
quelle
1
Sie können wahrscheinlich auch den Unity-Line-Renderer verwenden und zusätzliche Punkte einfügen, um eine kleine Gehrung zu erstellen. Setzen Sie einfach einen Punkt ein Stück weiter zum nächsten Punkt vom vorherigen Punkt.
Mklingen
Tolle Erklärung Byte, danke. Ich werde wahrscheinlich versuchen zu sehen, ob ich nicht an jeder Ecke mehr Punkte generieren kann. Wenn das nicht gut funktioniert, werde ich versuchen, ein dynamisches Netz zu erstellen. Vielen Dank.
Douglas Gaskell
1

Ich hatte das gleiche Problem und ich löse es, indem ich mehr Punkte zu glatten Kanten hinzufüge. Es ist keine elegante Lösung, aber es ist einfach und funktioniert. Zumindest für mich. Ich habe eine Funktion geschrieben, um dies zu tun:

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;
}
Miguel Ángel Llorente
quelle
Dies kann jetzt umstritten
DMGregory
0

Eine Möglichkeit, dies für undurchsichtige Linien zu lösen, besteht darin, an jeder Fuge einen Kreis zu rendern. Der Kreis muss einen Durchmesser haben, der der Linienbreite entspricht. Dies erfordert ein paar zusätzliche Eckpunkte zum Rendern, sieht aber wirklich gut aus. Sie können dann auch die gemeinsamen Normalen zwischen den Gelenken entfernen.

Dies erfordert weiterhin, dass Sie Ihren eigenen Rendering-Code schreiben, anstatt den Unity Line Renderer zu verwenden.

Ich habe unter http://u3d.as/nFE einen Vermögenswert erstellt, der genau dies tut

jjxtra
quelle
0

Ich habe dies vermieden, indem ich die z-Position in der LineRenderer.SetPosition () -Methode immer auf 0 gesetzt habe. Also anstatt zu schreiben

LineRenderer.SetPosition(i, myVector3);

Ich hab geschrieben

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

Aber das ist nicht die beste Lösung, da Sie immer noch diese seltsamen Zeilen bekommen. Die beste Lösung, die ich mir vorstellen konnte, war das Erstellen separater Zeilen. Das hat bei mir perfekt funktioniert. Hoffe das hilft dir.

Alexionder
quelle