ラインレンダラーラインをフラットに保つ方法は?


10

Line Rendererラインに頂点を追加すると、ラインがねじれて滑らかなラインでなくなることに気付きました。

ここに画像の説明を入力してください

.GIFこちら:http : //i.imgur.com/hRAhCXM.gif

すべての線が同じzレベルにあります。材料を削除しても、線はまだねじれているようです。

なぜこれが行われるのか、またはどのように解決するのか、提案がありますか?


これは、頂点を配置するためにLineRendererが使用するアルゴリズムの問​​題であり、鋭い角をうまく処理できません。コーナーを丸めるためにポイントを追加することで多少改善できますが、私が見つけた最も堅牢な方法は、必要な頂点でダイナミックメッシュを作成するか、創造的に、より良いアルゴリズムで機能を複製することですParticleSystemを利用してポイントのチェーンを描画します。
DMGregory

1
更新: Unityの新しいバージョン(5 5+)ではLineRendererアルゴリズムが改善されたため、LineRenderersの使用を検討しているユーザーは、すぐに使える結果が最近の方が大幅に優れていることに気付くかもしれません。
DMGregory

回答:


11

問題は基本的にこれです:

ここに画像の説明を入力してください

LineRendererは赤い点の位置を接続しようとしています。緑の頂点を作成してメッシュを作成しています。したがって、一番上のラインセグメントは見栄えがします。しかし、その後、LineRendererは経済的になることを試み、1つのラインセグメントの終わりから2番目のラインセグメントの終わりに頂点を再利用します。鋭角があると、目に見える問題が発生します。2番目の線分は、その「エンドキャップ」が他の「エンドキャップ」と垂直ではないため、交点でつまんでいます。

解決策は、独自のラインレンダラーを作成することであり、それほど経済的ではありません。これを行うには、動的メッシュを生成します。メッシュは一連の薄い四角形で構成されます。各ラインセグメントについて、ラインの法線と指定されたライン幅を計算することにより、クワッドの4つのコーナーを計算できます。

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

ここで、abcおよびd真上画像における緑のドットのように、単一の線分の四隅を構成します。これらの頂点はメッシュに追加されます。また、インデックスを追加して、4つの頂点を2つの三角形にします(したがって、abcとbdcの6つのインデックスが追加されます)。

これは明らかにかなり複雑になる可能性があります。UnityがLineRendererを彼らが行った方法で実装したもう1つの理由は、その方法で別の問題を回避できるためだと思います。各ラインセグメントの描画を開始すると、2つのラインセグメントが結合して醜いジョイントを形成する場所がわかります。両方の線の間の共有法線を計算し、それらの頂点を共有法線に更新することによってこれに対処する方法がありますが、これは問題を部分的にしか解決しません。最も堅牢なソリューションは、コーナーとして機能するようにジョイントに追加の頂点を生成することです。


1
また、ユニティラインレンダラーを使用し、追加のポイントを挿入して小さなマイターを作成することもできます。前のポイントから次のポイントに向かって少しだけポイントを置くだけです。
mklingen 2015

素晴らしい説明バイト、ありがとう。おそらく、各コーナーでこれ以上ポイントを生成できないかどうかを試してみます。それがうまくいかない場合は、先に進んでダイナミックメッシュを作成してみます。ありがとうございました。
Douglas Gaskell 2015

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

不透明な線についてこれを解決する1つの方法は、各ジョイントで円をレンダリングすることです。円の直径は線幅と同じである必要があります。これは、レンダリングするためにいくつかの追加の頂点を必要としますが、本当に見栄えがします。その後、ジョイント間の共有法線を取り除くこともできます。

この場合でも、Unity Line Rendererを使用する代わりに、独自のレンダリングコードを作成する必要があります。

これを行うアセットをhttp://u3d.as/nFEで作成しました


0

これを回避する方法は、LineRenderer.SetPosition()メソッドで常にz位置を0に設定することです。だから書く代わりに

LineRenderer.SetPosition(i, myVector3);

私が書いた

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

しかし、これらの奇妙な線が表示されるため、これは最良の解決策ではありません。私が考えることができる最良の解決策は、別々の行を作成することでした。それは私には完璧に働きました。これがお役に立てば幸いです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.