Come fare in modo che le linee di Line Renderer restino piatte?


10

Ho notato che quando aggiungo più vertici a una linea di Line Renderer, la linea si attorciglia e smette di essere una linea liscia.

inserisci qui la descrizione dell'immagine

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

Tutte le linee sono sullo stesso livello z, anche se rimuovo i materiali le linee sembrano ancora torcere.

Non ho idea del perché lo faccia o di come risolverlo, qualche suggerimento? C #


Questo è un problema con l'algoritmo che LineRenderer usa per posizionare i suoi vertici, che affronta male gli angoli acuti. Puoi migliorarlo un po 'aggiungendo più punti per arrotondare gli angoli, ma il metodo più efficace che ho trovato è duplicare la sua funzionalità con un algoritmo migliore, creando una mesh dinamica con i vertici di cui hai bisogno, o in modo creativo sfruttando un sistema particellare per disegnare la catena di punti.
DMGregory

1
Aggiornamento: le versioni successive di Unity (5 5+) hanno migliorato l'algoritmo LineRenderer , quindi gli utenti che considerano l'utilizzo di LineRenderer potrebbero trovare il risultato immediato attualmente sostanzialmente migliore.
DMGregory

Risposte:


11

Il problema è sostanzialmente questo:

inserisci qui la descrizione dell'immagine

LineRenderer sta tentando di collegare le posizioni dei punti rossi. Sta creando i vertici verdi per creare una mesh. Quindi il segmento della linea superiore sembra fantastico. Ma poi il LineRenderer cerca di essere economico, riutilizza i vertici dalla fine di un segmento di linea alla fine del secondo segmento di linea. Quando c'è un angolo acuto, ottieni il problema che stai vedendo. Il segmento della seconda linea viene pizzicato all'intersezione perché il suo "cappuccio" non è perpendicolare con l'altro "tappo".

La soluzione è creare il tuo renderizzatore di linee e non renderlo così economico. Puoi farlo generando una mesh dinamica . La mesh sarà composta da una serie di quadratini sottili. Per ogni segmento di linea, è possibile calcolare i quattro angoli del quadrato calcolando la normale della linea e una larghezza della linea specificata:

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

Qui, a, b, ce dcostituiscono i quattro angoli di un singolo segmento di linea, proprio come i punti verdi nell'immagine qui sopra. Questi vertici verrebbero aggiunti alla mesh e aggiungerei anche gli indici per rendere i quattro vertici in due triangoli (quindi, verranno aggiunti sei indici, abc e bdc).

Questo può ovviamente diventare piuttosto complesso. Credo che un altro motivo per cui Unity abbia implementato il loro LineRenderer nel modo in cui lo hanno fatto sia perché farlo in questo modo evita un altro problema, gli angoli. Quando inizi a disegnare ogni segmento di linea, inizierai a vedere dove i due segmenti di linea si uniscono e formano una brutta giuntura. Esistono modi per affrontarlo calcolando la normale condivisa tra entrambe le linee e aggiornando i loro vertici alla normale condivisa, ma questo risolve solo parzialmente il problema, poiché puoi ancora facilmente finire con le linee pizzicate. La soluzione più robusta è quella di generare vertici aggiuntivi sui giunti per agire come angoli.


1
Probabilmente puoi anche cavartela usando il renderer della linea di unità e inserendo punti aggiuntivi per creare un piccolo mitra. Basta mettere un punto un po 'verso il punto successivo al punto precedente.
mklingen,

Grande spiegazione Byte, grazie. Probabilmente proverò a vedere se non riesco a generare più punti in ciascuno degli angoli, se ciò non funziona bene, andrò avanti e cercherò di creare una mesh dinamica. Grazie.
Douglas Gaskell,

1

Ho avuto lo stesso problema e lo risolvo aggiungendo più punti ai bordi smussati non è una soluzione elegante ma è semplice e funziona. Almeno per me. Ho scritto una funzione per fare questo:

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

Un modo per risolvere questo problema per le linee opache consiste nel rendere un cerchio in corrispondenza di ciascuna giuntura. Il cerchio deve avere un diametro uguale alla larghezza della linea. Ciò richiede il rendering di alcuni vertici aggiuntivi, ma sembra davvero bello. È inoltre possibile eliminare le normali condivise tra le articolazioni.

Ciò richiede comunque di scrivere il proprio codice di rendering invece di utilizzare Unity Line Renderer.

Ho creato un asset che fa proprio questo su http://u3d.as/nFE


0

Il modo in cui l'ho evitato è che ho sempre impostato la posizione z su 0 nel metodo LineRenderer.SetPosition (). Quindi invece di scrivere

LineRenderer.SetPosition(i, myVector3);

scrissi

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

Ma questa non è la soluzione migliore in quanto otterrai comunque quelle strane linee. La migliore soluzione a cui potevo pensare era la creazione di linee separate. Ha funzionato perfettamente per me. Spero che questo ti aiuti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.